🎖️GitЯра🎖️
Node / meshtastic / Meshtastic-Android / files / core / service / src / androidMain / kotlin / org / meshtastic / core / service / MeshNotificationManagerImpl.kt
Displaying Raw • Download
core/service/src/androidMain/kotlin/org/meshtastic/core/service/MeshNotificationManagerImpl.kt d12fc8ebcf650222647385baabcf89ea5906969e (d12fc8eb) Text, 47.55 KB
T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.core.service
Tff7b72import T7ee787android.app.Notification
Tff7b72import T7ee787android.app.NotificationChannel
Tff7b72import T7ee787android.app.NotificationManager
Tff7b72import T7ee787android.app.PendingIntent
Tff7b72import T7ee787android.app.TaskStackBuilder
Tff7b72import T7ee787android.content.ContentResolver.SCHEME_ANDROID_RESOURCE
Tff7b72import T7ee787android.content.Context
Tff7b72import T7ee787android.content.Intent
Tff7b72import T7ee787android.media.AudioAttributes
Tff7b72import T7ee787android.media.RingtoneManager
Tff7b72import T7ee787androidx.core.app.NotificationCompat
Tff7b72import T7ee787androidx.core.app.Person
Tff7b72import T7ee787androidx.core.app.RemoteInput
Tff7b72import T7ee787androidx.core.content.LocusIdCompat
Tff7b72import T7ee787androidx.core.content.getSystemService
Tff7b72import T7ee787androidx.core.graphics.drawable.IconCompat
Tff7b72import T7ee787androidx.core.net.toUri
Tff7b72import T7ee787kotlinx.coroutines.flow.first
Tff7b72import T7ee787org.jetbrains.compose.resources.StringResource
Tff7b72import T7ee787org.koin.core.annotation.Single
Tff7b72import T7ee787org.meshtastic.core.common.util.NumberFormatter
Tff7b72import T7ee787org.meshtastic.core.common.util.nowMillis
Tff7b72import T7ee787org.meshtastic.core.model.Channel
Tff7b72import T7ee787org.meshtastic.core.model.ConnectionState
Tff7b72import T7ee787org.meshtastic.core.model.Message
Tff7b72import T7ee787org.meshtastic.core.model.Node
Tff7b72import T7ee787org.meshtastic.core.model.NodeAddress
Tff7b72import T7ee787org.meshtastic.core.model.util.formatUptime
Tff7b72import T7ee787org.meshtastic.core.navigation.DEEP_LINK_BASE_URI
Tff7b72import T7ee787org.meshtastic.core.repository.MeshNotificationManager
Tff7b72import T7ee787org.meshtastic.core.repository.NodeRepository
Tff7b72import T7ee787org.meshtastic.core.repository.PacketRepository
Tff7b72import T7ee787org.meshtastic.core.repository.RadioConfigRepository
Tff7b72import T7ee787org.meshtastic.core.repository.SERVICE_NOTIFY_ID
Tff7b72import T7ee787org.meshtastic.core.resources.R.drawable
Tff7b72import T7ee787org.meshtastic.core.resources.R.raw
Tff7b72import T7ee787org.meshtastic.core.resources.Res
Tff7b72import T7ee787org.meshtastic.core.resources.channel
Tff7b72import T7ee787org.meshtastic.core.resources.client_notification
Tff7b72import T7ee787org.meshtastic.core.resources.connected
Tff7b72import T7ee787org.meshtastic.core.resources.connecting
Tff7b72import T7ee787org.meshtastic.core.resources.device_sleeping
Tff7b72import T7ee787org.meshtastic.core.resources.disconnected
Tff7b72import T7ee787org.meshtastic.core.resources.getString
Tff7b72import T7ee787org.meshtastic.core.resources.local_stats_bad
Tff7b72import T7ee787org.meshtastic.core.resources.local_stats_battery
Tff7b72import T7ee787org.meshtastic.core.resources.local_stats_diagnostics_prefix
Tff7b72import T7ee787org.meshtastic.core.resources.local_stats_dropped
Tff7b72import T7ee787org.meshtastic.core.resources.local_stats_heap
Tff7b72import T7ee787org.meshtastic.core.resources.local_stats_heap_value
Tff7b72import T7ee787org.meshtastic.core.resources.local_stats_nodes
Tff7b72import T7ee787org.meshtastic.core.resources.local_stats_noise
Tff7b72import T7ee787org.meshtastic.core.resources.local_stats_relays
Tff7b72import T7ee787org.meshtastic.core.resources.local_stats_traffic
Tff7b72import T7ee787org.meshtastic.core.resources.local_stats_uptime
Tff7b72import T7ee787org.meshtastic.core.resources.local_stats_utilization
Tff7b72import T7ee787org.meshtastic.core.resources.low_battery_message
Tff7b72import T7ee787org.meshtastic.core.resources.low_battery_title
Tff7b72import T7ee787org.meshtastic.core.resources.mark_as_read
Tff7b72import T7ee787org.meshtastic.core.resources.meshtastic_alerts_notifications
Tff7b72import T7ee787org.meshtastic.core.resources.meshtastic_app_name
Tff7b72import T7ee787org.meshtastic.core.resources.meshtastic_broadcast_notifications
Tff7b72import T7ee787org.meshtastic.core.resources.meshtastic_low_battery_notifications
Tff7b72import T7ee787org.meshtastic.core.resources.meshtastic_low_battery_temporary_remote_notifications
Tff7b72import T7ee787org.meshtastic.core.resources.meshtastic_messages_notifications
Tff7b72import T7ee787org.meshtastic.core.resources.meshtastic_new_nodes_notifications
Tff7b72import T7ee787org.meshtastic.core.resources.meshtastic_service_notifications
Tff7b72import T7ee787org.meshtastic.core.resources.meshtastic_waypoints_notifications
Tff7b72import T7ee787org.meshtastic.core.resources.new_node_seen
Tff7b72import T7ee787org.meshtastic.core.resources.no_local_stats
Tff7b72import T7ee787org.meshtastic.core.resources.powered
Tff7b72import T7ee787org.meshtastic.core.resources.reply
Tff7b72import T7ee787org.meshtastic.core.resources.unknown_username
Tff7b72import T7ee787org.meshtastic.core.resources.you
Tff7b72import T7ee787org.meshtastic.core.service.MarkAsReadReceiver.Companion.MARK_AS_READ_ACTION
Tff7b72import T7ee787org.meshtastic.core.service.ReactionReceiver.Companion.REACT_ACTION
Tff7b72import T7ee787org.meshtastic.core.service.ReplyReceiver.Companion.KEY_TEXT_REPLY
Tff7b72import T7ee787org.meshtastic.proto.ClientNotification
Tff7b72import T7ee787org.meshtastic.proto.DeviceMetrics
Tff7b72import T7ee787org.meshtastic.proto.LocalStats
Tff7b72import T7ee787org.meshtastic.proto.Telemetry
Tff7b72import T7ee787java.util.concurrent.ConcurrentHashMap
Tff7b72import T7ee787kotlin.time.Duration.Companion.minutes
T8b949e/**
* Manages the creation and display of all app notifications.
*
* This class centralizes notification logic, including channel creation, builder configuration, and displaying
* notifications for various events like new messages, alerts, and service status changes.
*/
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffTooManyFunctionsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffLongParameterListTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffLargeClassTa5d6ff"Tb4b4b4)
Tf0883e@Single
Tff7b72class T56d364MeshNotificationManagerImplTb4b4b4(
Tff7b72private Tff7b72val Te6edf3contextTb4b4b4: Te6edf3ContextTb4b4b4,
Tff7b72private Tff7b72val Te6edf3packetRepositoryTb4b4b4: Te6edf3LazyTff7b72<Te6edf3PacketRepositoryTff7b72>Tb4b4b4,
Tff7b72private Tff7b72val Te6edf3nodeRepositoryTb4b4b4: Te6edf3LazyTff7b72<Te6edf3NodeRepositoryTff7b72>Tb4b4b4,
Tff7b72private Tff7b72val Te6edf3conversationShortcutPublisherTb4b4b4: Te6edf3LazyTff7b72<Te6edf3ConversationShortcutPublisherTff7b72>Tb4b4b4,
Tff7b72private Tff7b72val Te6edf3radioConfigRepositoryTb4b4b4: Te6edf3LazyTff7b72<Te6edf3RadioConfigRepositoryTff7b72>Tb4b4b4,
Tb4b4b4) Tb4b4b4: Te6edf3MeshNotificationManager Tb4b4b4{
Tff7b72private Tff7b72val Te6edf3notificationManager Tff7b72=
Te6edf3checkNotNullTb4b4b4(Te6edf3contextTb4b4b4.Te6edf3getSystemServiceTff7b72<Te6edf3NotificationManagerTff7b72>Tb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffNotificationManager not foundTa5d6ff" Tb4b4b4}
Tff7b72companion Tff7b72object Tb4b4b4{
Tff7b72const Tff7b72val Te6edf3MAX_BATTERY_LEVEL Tff7b72= T79c0ff1T79c0ff0T79c0ff0
T8b949e// Meshtastic brand accent (Green 500, see .skills/design-standards) — used as the notification accent color
T8b949e// (small-icon tint) and the notification LED color.
Tff7b72private Tff7b72val Te6edf3NOTIFICATION_COLOR Tff7b72= T79c0ff0Te6edf3xFF67EA94Tb4b4b4.Te6edf3toIntTb4b4b4(Tb4b4b4)
Tff7b72private Tff7b72const Tff7b72val Te6edf3MAX_HISTORY_MESSAGES Tff7b72= T79c0ff1T79c0ff0
Tff7b72private Tff7b72const Tff7b72val Te6edf3MIN_CONTEXT_MESSAGES Tff7b72= T79c0ff3
Tff7b72private Tff7b72const Tff7b72val Te6edf3SNIPPET_LENGTH Tff7b72= T79c0ff3T79c0ff0
Tff7b72private Tff7b72const Tff7b72val Te6edf3GROUP_KEY_MESSAGES Tff7b72= Ta5d6ff"Ta5d6fforg.meshtastic.app.GROUP_MESSAGESTa5d6ff"
Tff7b72private Tff7b72const Tff7b72val Te6edf3SUMMARY_ID Tff7b72= T79c0ff1
Tff7b72private Tff7b72const Tff7b72val Te6edf3STATS_UPDATE_MINUTES Tff7b72= T79c0ff1T79c0ff5
Tff7b72private Tff7b72val Te6edf3STATS_UPDATE_INTERVAL Tff7b72= Te6edf3STATS_UPDATE_MINUTESTb4b4b4.Te6edf3minutes
Tff7b72private Tff7b72const Tff7b72val Te6edf3BULLET Tff7b72= Ta5d6ff"Ta5d6ff• Ta5d6ff"
T8b949e// Notification tags namespace the numeric IDs per notification type. Without them every type shares one
T8b949e// integer ID space, so unrelated notifications can clobber each other (e.g. a node whose num == 101 would
T8b949e// overwrite the foreground-service notification, or num == 1 the group summary). notify()/cancel() must use
T8b949e// the same (tag, id) pair.
Tff7b72private Tff7b72const Tff7b72val Te6edf3TAG_MESSAGE Tff7b72= Ta5d6ff"Ta5d6ffmessageTa5d6ff"
Tff7b72private Tff7b72const Tff7b72val Te6edf3TAG_MESSAGE_SUMMARY Tff7b72= Ta5d6ff"Ta5d6ffmessage_summaryTa5d6ff"
Tff7b72private Tff7b72const Tff7b72val Te6edf3TAG_WAYPOINT Tff7b72= Ta5d6ff"Ta5d6ffwaypointTa5d6ff"
Tff7b72private Tff7b72const Tff7b72val Te6edf3TAG_ALERT Tff7b72= Ta5d6ff"Ta5d6ffalertTa5d6ff"
Tff7b72private Tff7b72const Tff7b72val Te6edf3TAG_NEW_NODE Tff7b72= Ta5d6ff"Ta5d6ffnew_nodeTa5d6ff"
Tff7b72private Tff7b72const Tff7b72val Te6edf3TAG_LOW_BATTERY Tff7b72= Ta5d6ff"Ta5d6fflow_batteryTa5d6ff"
Tff7b72private Tff7b72const Tff7b72val Te6edf3TAG_CLIENT Tff7b72= Ta5d6ff"Ta5d6ffclientTa5d6ff"
Tb4b4b4}
T8b949e/**
* Caches generated avatar icons keyed by (person id + short name + colors) so a conversation rebuild does not
* re-rasterize an avatar bitmap for every message on every update. Bounded by the number of distinct nodes seen;
* entries are cheap and colors/names rarely change.
*/
Tff7b72private Tff7b72val Te6edf3personIconCache Tff7b72= Te6edf3ConcurrentHashMapTff7b72<Tffa657StringTb4b4b4, Te6edf3IconCompatTff7b72>Tb4b4b4(Tb4b4b4)
T8b949e/** Circular, node-colored avatar holding the sender's full short name (e.g. "2c3d"), not just its first letter. */
Tff7b72private Tff7b72fun Td2a8ffcachedPersonIconTb4b4b4(Te6edf3keyTb4b4b4: Tffa657StringTb4b4b4, Te6edf3shortNameTb4b4b4: Tffa657StringTb4b4b4, Te6edf3backgroundColorTb4b4b4: Tffa657IntTb4b4b4, Te6edf3foregroundColorTb4b4b4: Tffa657IntTb4b4b4) Tff7b72=
Te6edf3personIconCacheTb4b4b4.Te6edf3getOrPutTb4b4b4(Ta5d6ff"Tffd700$Te6edf3keyTa5d6ff|Tffd700$Te6edf3shortNameTa5d6ff|Tffd700$Te6edf3backgroundColorTa5d6ff|Tffd700$Te6edf3foregroundColorTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3PersonIconFactoryTb4b4b4.Te6edf3createLabelTb4b4b4(Te6edf3shortNameTb4b4b4, Te6edf3backgroundColorTb4b4b4, Te6edf3foregroundColorTb4b4b4, Te6edf3rounded Tff7b72= Tff7b72falseTb4b4b4)
Tb4b4b4}
T8b949e/**
* Sealed class to define the properties of each notification channel. This centralizes channel configuration and
* makes it type-safe.
*/
Tff7b72private Tff7b72sealed Tff7b72class T56d364NotificationTypeTb4b4b4(
Tff7b72val Te6edf3channelIdTb4b4b4: Tffa657StringTb4b4b4,
Tff7b72val Te6edf3channelNameResTb4b4b4: Te6edf3StringResourceTb4b4b4,
Tff7b72val Te6edf3importanceTb4b4b4: Tffa657IntTb4b4b4,
Tb4b4b4) Tb4b4b4{
Tff7b72object T56d364ServiceState Tb4b4b4:
Te6edf3NotificationTypeTb4b4b4(
Te6edf3NotificationChannelsTb4b4b4.Te6edf3SERVICETb4b4b4,
Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3meshtastic_service_notificationsTb4b4b4,
Te6edf3NotificationManagerTb4b4b4.Te6edf3IMPORTANCE_MINTb4b4b4,
Tb4b4b4)
Tff7b72object T56d364DirectMessage Tb4b4b4:
Te6edf3NotificationTypeTb4b4b4(
Te6edf3NotificationChannelsTb4b4b4.Te6edf3MESSAGESTb4b4b4,
Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3meshtastic_messages_notificationsTb4b4b4,
Te6edf3NotificationManagerTb4b4b4.Te6edf3IMPORTANCE_HIGHTb4b4b4,
Tb4b4b4)
Tff7b72object T56d364BroadcastMessage Tb4b4b4:
Te6edf3NotificationTypeTb4b4b4(
Te6edf3NotificationChannelsTb4b4b4.Te6edf3BROADCASTSTb4b4b4,
Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3meshtastic_broadcast_notificationsTb4b4b4,
Te6edf3NotificationManagerTb4b4b4.Te6edf3IMPORTANCE_DEFAULTTb4b4b4,
Tb4b4b4)
Tff7b72object T56d364Waypoint Tb4b4b4:
Te6edf3NotificationTypeTb4b4b4(
Te6edf3NotificationChannelsTb4b4b4.Te6edf3WAYPOINTSTb4b4b4,
Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3meshtastic_waypoints_notificationsTb4b4b4,
Te6edf3NotificationManagerTb4b4b4.Te6edf3IMPORTANCE_DEFAULTTb4b4b4,
Tb4b4b4)
Tff7b72object T56d364Alert Tb4b4b4:
Te6edf3NotificationTypeTb4b4b4(
Te6edf3NotificationChannelsTb4b4b4.Te6edf3ALERTSTb4b4b4,
Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3meshtastic_alerts_notificationsTb4b4b4,
Te6edf3NotificationManagerTb4b4b4.Te6edf3IMPORTANCE_HIGHTb4b4b4,
Tb4b4b4)
Tff7b72object T56d364NewNode Tb4b4b4:
Te6edf3NotificationTypeTb4b4b4(
Te6edf3NotificationChannelsTb4b4b4.Te6edf3NEW_NODESTb4b4b4,
Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3meshtastic_new_nodes_notificationsTb4b4b4,
Te6edf3NotificationManagerTb4b4b4.Te6edf3IMPORTANCE_DEFAULTTb4b4b4,
Tb4b4b4)
Tff7b72object T56d364LowBatteryLocal Tb4b4b4:
Te6edf3NotificationTypeTb4b4b4(
Te6edf3NotificationChannelsTb4b4b4.Te6edf3LOW_BATTERYTb4b4b4,
Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3meshtastic_low_battery_notificationsTb4b4b4,
Te6edf3NotificationManagerTb4b4b4.Te6edf3IMPORTANCE_DEFAULTTb4b4b4,
Tb4b4b4)
Tff7b72object T56d364LowBatteryRemote Tb4b4b4:
Te6edf3NotificationTypeTb4b4b4(
Te6edf3NotificationChannelsTb4b4b4.Te6edf3LOW_BATTERY_REMOTETb4b4b4,
Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3meshtastic_low_battery_temporary_remote_notificationsTb4b4b4,
Te6edf3NotificationManagerTb4b4b4.Te6edf3IMPORTANCE_DEFAULTTb4b4b4,
Tb4b4b4)
Tff7b72object T56d364Client Tb4b4b4:
Te6edf3NotificationTypeTb4b4b4(
Te6edf3NotificationChannelsTb4b4b4.Te6edf3CLIENTTb4b4b4,
Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3client_notificationTb4b4b4,
Te6edf3NotificationManagerTb4b4b4.Te6edf3IMPORTANCE_HIGHTb4b4b4,
Tb4b4b4)
Tff7b72companion Tff7b72object Tb4b4b4{
T8b949e// A list of all types for easy initialization.
Tff7b72fun Td2a8ffallTypesTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3listOfTb4b4b4(
Te6edf3ServiceStateTb4b4b4,
Te6edf3DirectMessageTb4b4b4,
Te6edf3BroadcastMessageTb4b4b4,
Te6edf3WaypointTb4b4b4,
Te6edf3AlertTb4b4b4,
Te6edf3NewNodeTb4b4b4,
Te6edf3LowBatteryLocalTb4b4b4,
Te6edf3LowBatteryRemoteTb4b4b4,
Te6edf3ClientTb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffclearNotificationsTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3notificationManagerTb4b4b4.Te6edf3cancelAllTb4b4b4(Tb4b4b4)
Tb4b4b4}
T8b949e/**
* Creates all necessary notification channels on devices running Android O or newer. This should be called once
* when the service is created.
*/
Tff7b72override Tff7b72fun Td2a8ffinitChannelsTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3notificationManagerTb4b4b4.Te6edf3removeLegacyCategoryChannelsTb4b4b4(Tb4b4b4)
Te6edf3NotificationTypeTb4b4b4.Te6edf3allTypesTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3forEach Tb4b4b4{ Te6edf3type Tff7b72-Tff7b72> Te6edf3createNotificationChannelTb4b4b4(Te6edf3typeTb4b4b4) Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffcreateNotificationChannelTb4b4b4(Te6edf3typeTb4b4b4: Te6edf3NotificationTypeTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3notificationManagerTb4b4b4.Te6edf3getNotificationChannelTb4b4b4(Te6edf3typeTb4b4b4.Te6edf3channelIdTb4b4b4) Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Tff7b72return
Tff7b72val Te6edf3channelName Tff7b72= Te6edf3getStringTb4b4b4(Te6edf3typeTb4b4b4.Te6edf3channelNameResTb4b4b4)
Tff7b72val Te6edf3channel Tff7b72=
Te6edf3NotificationChannelTb4b4b4(Te6edf3typeTb4b4b4.Te6edf3channelIdTb4b4b4, Te6edf3channelNameTb4b4b4, Te6edf3typeTb4b4b4.Te6edf3importanceTb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{
Te6edf3lightColor Tff7b72= Te6edf3NOTIFICATION_COLOR
Te6edf3lockscreenVisibility Tff7b72= Te6edf3NotificationTb4b4b4.Te6edf3VISIBILITY_PUBLIC T8b949e// Default, can be overridden
T8b949e// Type-specific configurations
Tff7b72when Tb4b4b4(Te6edf3typeTb4b4b4) Tb4b4b4{
Te6edf3NotificationTypeTb4b4b4.Te6edf3ServiceState Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3lockscreenVisibility Tff7b72= Te6edf3NotificationTb4b4b4.Te6edf3VISIBILITY_PRIVATE
Tb4b4b4}
Te6edf3NotificationTypeTb4b4b4.Te6edf3DirectMessageTb4b4b4,
Te6edf3NotificationTypeTb4b4b4.Te6edf3BroadcastMessageTb4b4b4,
Te6edf3NotificationTypeTb4b4b4.Te6edf3WaypointTb4b4b4,
Te6edf3NotificationTypeTb4b4b4.Te6edf3NewNodeTb4b4b4,
Te6edf3NotificationTypeTb4b4b4.Te6edf3LowBatteryLocalTb4b4b4,
Te6edf3NotificationTypeTb4b4b4.Te6edf3LowBatteryRemoteTb4b4b4,
Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3setShowBadgeTb4b4b4(Tff7b72trueTb4b4b4)
Te6edf3setSoundTb4b4b4(
Te6edf3RingtoneManagerTb4b4b4.Te6edf3getDefaultUriTb4b4b4(Te6edf3RingtoneManagerTb4b4b4.Te6edf3TYPE_NOTIFICATIONTb4b4b4)Tb4b4b4,
Te6edf3AudioAttributesTb4b4b4.Te6edf3BuilderTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3setUsageTb4b4b4(Te6edf3AudioAttributesTb4b4b4.Te6edf3USAGE_NOTIFICATIONTb4b4b4)
Tb4b4b4.Te6edf3setContentTypeTb4b4b4(Te6edf3AudioAttributesTb4b4b4.Te6edf3CONTENT_TYPE_SONIFICATIONTb4b4b4)
Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3type Tff7b72=Tff7b72= Te6edf3NotificationTypeTb4b4b4.Te6edf3LowBatteryRemoteTb4b4b4) Te6edf3enableVibrationTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4}
Te6edf3NotificationTypeTb4b4b4.Te6edf3Alert Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3setShowBadgeTb4b4b4(Tff7b72trueTb4b4b4)
Te6edf3enableLightsTb4b4b4(Tff7b72trueTb4b4b4)
Te6edf3enableVibrationTb4b4b4(Tff7b72trueTb4b4b4)
Te6edf3setBypassDndTb4b4b4(Tff7b72trueTb4b4b4)
Tff7b72val Te6edf3alertSoundUri Tff7b72=
Ta5d6ff"Tffd700${Te6edf3SCHEME_ANDROID_RESOURCETffd700}Ta5d6ff://Tffd700${Te6edf3contextTb4b4b4.Te6edf3packageNameTffd700}Ta5d6ff/Tffd700${Te6edf3rawTb4b4b4.Te6edf3meshtastic_alertTffd700}Ta5d6ff"Tb4b4b4.Te6edf3toUriTb4b4b4(Tb4b4b4)
Te6edf3setSoundTb4b4b4(
Te6edf3alertSoundUriTb4b4b4,
Te6edf3AudioAttributesTb4b4b4.Te6edf3BuilderTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3setUsageTb4b4b4(Te6edf3AudioAttributesTb4b4b4.Te6edf3USAGE_ALARMTb4b4b4) T8b949e// More appropriate for an alert
Tb4b4b4.Te6edf3setContentTypeTb4b4b4(Te6edf3AudioAttributesTb4b4b4.Te6edf3CONTENT_TYPE_SONIFICATIONTb4b4b4)
Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Te6edf3NotificationTypeTb4b4b4.Te6edf3Client Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3setShowBadgeTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Te6edf3notificationManagerTb4b4b4.Te6edf3createNotificationChannelTb4b4b4(Te6edf3channelTb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72var Te6edf3cachedDeviceMetricsTb4b4b4: Te6edf3DeviceMetrics? Tff7b72= Tff7b72null
Tff7b72private Tff7b72var Te6edf3cachedLocalStatsTb4b4b4: Te6edf3LocalStats? Tff7b72= Tff7b72null
Tff7b72private Tff7b72var Te6edf3nextStatsUpdateMillisTb4b4b4: Tffa657Long Tff7b72= T79c0ff0
Tff7b72private Tff7b72var Te6edf3cachedMessageTb4b4b4: Tffa657String? Tff7b72= Tff7b72null
Tff7b72private Tff7b72var Te6edf3cachedServiceNotificationTb4b4b4: Te6edf3Notification? Tff7b72= Tff7b72null
T8b949e/**
* Returns the last-built service state notification, or builds a default one if none exists. This is used by
* [MeshService] for [android.app.Service.startForeground].
*/
Tff7b72fun Td2a8ffgetServiceNotificationTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3Notification Tff7b72= Te6edf3cachedServiceNotification
Tff7b72?: Te6edf3createServiceStateNotificationTb4b4b4(
Te6edf3name Tff7b72= Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3meshtastic_app_nameTb4b4b4)Tb4b4b4,
Te6edf3message Tff7b72= Tff7b72nullTb4b4b4,
Te6edf3nextUpdateAt Tff7b72= T79c0ff0Tb4b4b4,
Tb4b4b4)
T8b949e// region Public Notification Methods
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffCyclomaticComplexMethodTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffNestedBlockDepthTa5d6ff"Tb4b4b4)
Tff7b72override Tff7b72fun Td2a8ffupdateServiceStateNotificationTb4b4b4(Te6edf3stateTb4b4b4: Te6edf3ConnectionStateTb4b4b4, Te6edf3telemetryTb4b4b4: Te6edf3Telemetry?Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3summaryString Tff7b72=
Tff7b72when Tb4b4b4(Te6edf3stateTb4b4b4) Tb4b4b4{
Tff7b72is Te6edf3ConnectionStateTb4b4b4.Te6edf3Connected Tff7b72-Tff7b72>
Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3meshtastic_app_nameTb4b4b4) Tff7b72+ Ta5d6ff"Ta5d6ff: Ta5d6ff" Tff7b72+ Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3connectedTb4b4b4)
Tff7b72is Te6edf3ConnectionStateTb4b4b4.Te6edf3Disconnected Tff7b72-Tff7b72> Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3disconnectedTb4b4b4)
Tff7b72is Te6edf3ConnectionStateTb4b4b4.Te6edf3DeviceSleep Tff7b72-Tff7b72> Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3device_sleepingTb4b4b4)
Tff7b72is Te6edf3ConnectionStateTb4b4b4.Te6edf3Connecting Tff7b72-Tff7b72> Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3connectingTb4b4b4)
Tb4b4b4}
T8b949e// Update caches if telemetry is provided
Te6edf3telemetryTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3t Tff7b72-Tff7b72>
Te6edf3tTb4b4b4.Te6edf3local_statsTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3stats Tff7b72-Tff7b72>
Te6edf3cachedLocalStats Tff7b72= Te6edf3stats
Te6edf3nextStatsUpdateMillis Tff7b72= Te6edf3nowMillis Tff7b72+ Te6edf3STATS_UPDATE_INTERVALTb4b4b4.Te6edf3inWholeMilliseconds
Tb4b4b4}
Te6edf3tTb4b4b4.Te6edf3device_metricsTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3metrics Tff7b72-Tff7b72> Te6edf3cachedDeviceMetrics Tff7b72= Te6edf3metrics Tb4b4b4}
Tb4b4b4}
T8b949e// Seeding from database if caches are still null (e.g. on restart or reconnection)
Tff7b72if Tb4b4b4(Te6edf3cachedLocalStats Tff7b72=Tff7b72= Tff7b72null Tff7b72|Tff7b72| Te6edf3cachedDeviceMetrics Tff7b72=Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3repo Tff7b72= Te6edf3nodeRepositoryTb4b4b4.Te6edf3value
Tff7b72val Te6edf3myNodeNum Tff7b72= Te6edf3repoTb4b4b4.Te6edf3myNodeInfoTb4b4b4.Te6edf3valueTff7b72?.Te6edf3myNodeNum
Tff7b72if Tb4b4b4(Te6edf3myNodeNum Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
T8b949e// Use .value instead of runBlocking { .first() } to avoid potential deadlock
T8b949e// if called on the same dispatcher the Flow's upstream coroutine needs.
Tff7b72val Te6edf3nodes Tff7b72= Te6edf3repoTb4b4b4.Te6edf3nodeDBbyNumTb4b4b4.Te6edf3value
Te6edf3nodesTff7b72[Te6edf3myNodeNumTff7b72]Tff7b72?.Te6edf3let Tb4b4b4{ Te6edf3node Tff7b72-Tff7b72>
Tff7b72if Tb4b4b4(Te6edf3cachedDeviceMetrics Tff7b72=Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3cachedDeviceMetrics Tff7b72= Te6edf3nodeTb4b4b4.Te6edf3deviceMetrics
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3cachedLocalStats Tff7b72=Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
T8b949e// Fallback to DB stats if repository hasn't received any fresh ones yet
Te6edf3cachedLocalStats Tff7b72= Te6edf3repoTb4b4b4.Te6edf3localStatsTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3takeIf Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3uptime_seconds Tff7b72!Tff7b72= T79c0ff0 Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72val Te6edf3stats Tff7b72= Te6edf3cachedLocalStats
Tff7b72val Te6edf3metrics Tff7b72= Te6edf3cachedDeviceMetrics
Tff7b72val Te6edf3message Tff7b72=
Tff7b72when Tb4b4b4{
Te6edf3stats Tff7b72!Tff7b72= Tff7b72null Tff7b72-Tff7b72> Te6edf3statsTb4b4b4.Te6edf3formatToStringTb4b4b4(Te6edf3metricsTff7b72?.Te6edf3battery_levelTb4b4b4)
Te6edf3metrics Tff7b72!Tff7b72= Tff7b72null Tff7b72-Tff7b72> Te6edf3metricsTb4b4b4.Te6edf3formatToStringTb4b4b4(Tb4b4b4)
Tff7b72else Tff7b72-Tff7b72> Tff7b72null
Tb4b4b4}
T8b949e// Only update cachedMessage if we have something new, otherwise keep what we have.
T8b949e// Fallback to "No Stats Available" only if we truly have nothing.
Tff7b72if Tb4b4b4(Te6edf3message Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3cachedMessage Tff7b72= Te6edf3message
Tb4b4b4} Tff7b72else Tff7b72if Tb4b4b4(Te6edf3cachedMessage Tff7b72=Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3cachedMessage Tff7b72= Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3no_local_statsTb4b4b4)
Tb4b4b4}
Tff7b72val Te6edf3notification Tff7b72=
Te6edf3createServiceStateNotificationTb4b4b4(
Te6edf3name Tff7b72= Te6edf3summaryStringTb4b4b4.Te6edf3orEmptyTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3message Tff7b72= Te6edf3cachedMessageTb4b4b4,
Te6edf3nextUpdateAt Tff7b72= Te6edf3nextStatsUpdateMillisTb4b4b4,
Tb4b4b4)
Te6edf3cachedServiceNotification Tff7b72= Te6edf3notification
Te6edf3notificationManagerTb4b4b4.Te6edf3notifyTb4b4b4(Te6edf3SERVICE_NOTIFY_IDTb4b4b4, Te6edf3notificationTb4b4b4)
Tb4b4b4}
Tff7b72override Tff7b72suspend Tff7b72fun Td2a8ffupdateMessageNotificationTb4b4b4(
Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4,
Te6edf3nameTb4b4b4: Tffa657StringTb4b4b4,
Te6edf3messageTb4b4b4: Tffa657StringTb4b4b4,
Te6edf3isBroadcastTb4b4b4: Tffa657BooleanTb4b4b4,
Te6edf3channelNameTb4b4b4: Tffa657String?Tb4b4b4,
Te6edf3isSilentTb4b4b4: Tffa657BooleanTb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3showConversationNotificationTb4b4b4(Te6edf3contactKeyTb4b4b4, Te6edf3isBroadcastTb4b4b4, Te6edf3channelNameTb4b4b4, Te6edf3conversationName Tff7b72= Te6edf3nameTb4b4b4, Te6edf3isSilent Tff7b72= Te6edf3isSilentTb4b4b4)
Tb4b4b4}
Tff7b72override Tff7b72suspend Tff7b72fun Td2a8ffupdateReactionNotificationTb4b4b4(
Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4,
Te6edf3nameTb4b4b4: Tffa657StringTb4b4b4,
Te6edf3emojiTb4b4b4: Tffa657StringTb4b4b4,
Te6edf3isBroadcastTb4b4b4: Tffa657BooleanTb4b4b4,
Te6edf3channelNameTb4b4b4: Tffa657String?Tb4b4b4,
Te6edf3isSilentTb4b4b4: Tffa657BooleanTb4b4b4,
Tb4b4b4) Tb4b4b4{
Te6edf3showConversationNotificationTb4b4b4(Te6edf3contactKeyTb4b4b4, Te6edf3isBroadcastTb4b4b4, Te6edf3channelNameTb4b4b4, Te6edf3conversationName Tff7b72= Te6edf3nameTb4b4b4, Te6edf3isSilent Tff7b72= Te6edf3isSilentTb4b4b4)
Tb4b4b4}
Tff7b72override Tff7b72suspend Tff7b72fun Td2a8ffupdateWaypointNotificationTb4b4b4(
Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4,
Te6edf3nameTb4b4b4: Tffa657StringTb4b4b4,
Te6edf3messageTb4b4b4: Tffa657StringTb4b4b4,
Te6edf3waypointIdTb4b4b4: Tffa657IntTb4b4b4,
Te6edf3isSilentTb4b4b4: Tffa657BooleanTb4b4b4,
Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3notification Tff7b72= Te6edf3createWaypointNotificationTb4b4b4(Te6edf3nameTb4b4b4, Te6edf3messageTb4b4b4, Te6edf3waypointIdTb4b4b4, Te6edf3isSilentTb4b4b4)
Te6edf3notificationManagerTb4b4b4.Te6edf3notifyTb4b4b4(Te6edf3TAG_WAYPOINTTb4b4b4, Te6edf3contactKeyTb4b4b4.Te6edf3hashCodeTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3notificationTb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72suspend Tff7b72fun Td2a8ffshowConversationNotificationTb4b4b4(
Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4,
Te6edf3isBroadcastTb4b4b4: Tffa657BooleanTb4b4b4,
Te6edf3channelNameTb4b4b4: Tffa657String?Tb4b4b4,
Te6edf3conversationNameTb4b4b4: Tffa657StringTb4b4b4,
Te6edf3isSilentTb4b4b4: Tffa657Boolean Tff7b72= Tff7b72falseTb4b4b4,
Tb4b4b4) Tb4b4b4{
T8b949e// Publish (or refresh) a long-lived conversation shortcut before the notification references it, so Android can
T8b949e// rank the notification in the shade's Conversations section and expose it to Android Auto/Wear. A channel name
T8b949e// labels a broadcast conversation; a direct message is labelled by the other participant's name.
Te6edf3conversationShortcutPublisherTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3ensureConversationShortcutTb4b4b4(Te6edf3contactKeyTb4b4b4, Te6edf3channelName Tff7b72?: Te6edf3conversationNameTb4b4b4)
Tff7b72val Te6edf3ourNode Tff7b72= Te6edf3nodeRepositoryTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3ourNodeInfoTb4b4b4.Te6edf3value
Tff7b72val Te6edf3history Tff7b72=
Te6edf3packetRepositoryTb4b4b4.Te6edf3value
Tb4b4b4.Te6edf3getMessagesFromTb4b4b4(Te6edf3contactKeyTb4b4b4, Te6edf3includeFiltered Tff7b72= Tff7b72falseTb4b4b4) Tb4b4b4{ Te6edf3nodeId Tff7b72-Tff7b72>
Tff7b72if Tb4b4b4(Te6edf3nodeId Tff7b72=Tff7b72= Te6edf3NodeAddressTb4b4b4.Te6edf3ID_LOCALTb4b4b4) Tb4b4b4{
Te6edf3ourNode Tff7b72?: Te6edf3nodeRepositoryTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3getNodeTb4b4b4(Te6edf3nodeIdTb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3nodeRepositoryTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3getNodeTb4b4b4(Te6edf3nodeIdTb4b4b4.Te6edf3orEmptyTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3unread Tff7b72= Te6edf3historyTb4b4b4.Te6edf3filter Tb4b4b4{ Tff7b72!Tffa657itTb4b4b4.Te6edf3read Tb4b4b4}
Tff7b72val Te6edf3displayHistory Tff7b72=
Tff7b72if Tb4b4b4(Te6edf3unreadTb4b4b4.Te6edf3size Tff7b72< Te6edf3MIN_CONTEXT_MESSAGESTb4b4b4) Tb4b4b4{
Te6edf3historyTb4b4b4.Te6edf3takeTb4b4b4(Te6edf3MIN_CONTEXT_MESSAGESTb4b4b4)Tb4b4b4.Te6edf3reversedTb4b4b4(Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3unreadTb4b4b4.Te6edf3takeTb4b4b4(Te6edf3MAX_HISTORY_MESSAGESTb4b4b4)Tb4b4b4.Te6edf3reversedTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3displayHistoryTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72return
Tff7b72val Te6edf3notification Tff7b72=
Te6edf3createConversationNotificationTb4b4b4(
Te6edf3contactKey Tff7b72= Te6edf3contactKeyTb4b4b4,
Te6edf3isBroadcast Tff7b72= Te6edf3isBroadcastTb4b4b4,
Te6edf3channelName Tff7b72= Te6edf3channelNameTb4b4b4,
Te6edf3history Tff7b72= Te6edf3displayHistoryTb4b4b4,
Te6edf3isSilent Tff7b72= Te6edf3isSilentTb4b4b4,
Tb4b4b4)
Te6edf3notificationManagerTb4b4b4.Te6edf3notifyTb4b4b4(Te6edf3TAG_MESSAGETb4b4b4, Te6edf3contactKeyTb4b4b4.Te6edf3hashCodeTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3notificationTb4b4b4)
Te6edf3showGroupSummaryTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffshowGroupSummaryTb4b4b4(Te6edf3justCancelledIdTb4b4b4: Tffa657Int? Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
T8b949e// Exclude the summary itself by its group-summary flag rather than by id, so a conversation whose
T8b949e// contactKey.hashCode() happens to equal SUMMARY_ID is still counted as an active conversation.
T8b949e// Also exclude a conversation we just cancelled: activeNotifications does not reflect a cancel() issued
T8b949e// moments earlier, so without this the summary would be rebuilt from stale state and orphaned in the shade
T8b949e// (and Android Auto) after the last message is dismissed via reply / mark-as-read.
Tff7b72val Te6edf3activeNotifications Tff7b72=
Te6edf3notificationManagerTb4b4b4.Te6edf3activeNotificationsTb4b4b4.Te6edf3filter Tb4b4b4{
Tffa657itTb4b4b4.Te6edf3notificationTb4b4b4.Te6edf3group Tff7b72=Tff7b72= Te6edf3GROUP_KEY_MESSAGES Tff7b72&Tff7b72&
Tb4b4b4(Tffa657itTb4b4b4.Te6edf3notificationTb4b4b4.Te6edf3flags Te6edf3and Te6edf3NotificationTb4b4b4.Te6edf3FLAG_GROUP_SUMMARYTb4b4b4) Tff7b72=Tff7b72= T79c0ff0 Tff7b72&Tff7b72&
Tff7b72!Tb4b4b4(Tffa657itTb4b4b4.Te6edf3tag Tff7b72=Tff7b72= Te6edf3TAG_MESSAGE Tff7b72&Tff7b72& Tffa657itTb4b4b4.Te6edf3id Tff7b72=Tff7b72= Te6edf3justCancelledIdTb4b4b4)
Tb4b4b4}
T8b949e// No conversations left — drop the summary too, otherwise it lingers in Android Auto after the
T8b949e// last message notification is cancelled (e.g. on reply / mark-as-read).
Tff7b72if Tb4b4b4(Te6edf3activeNotificationsTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3notificationManagerTb4b4b4.Te6edf3cancelTb4b4b4(Te6edf3TAG_MESSAGE_SUMMARYTb4b4b4, Te6edf3SUMMARY_IDTb4b4b4)
Tff7b72return
Tb4b4b4}
Tff7b72val Te6edf3ourNode Tff7b72= Te6edf3nodeRepositoryTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3ourNodeInfoTb4b4b4.Te6edf3value
Tff7b72val Te6edf3meName Tff7b72= Te6edf3ourNodeTff7b72?.Te6edf3userTff7b72?.Te6edf3long_name Tff7b72?: Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3youTb4b4b4)
Tff7b72val Te6edf3me Tff7b72=
Te6edf3PersonTb4b4b4.Te6edf3BuilderTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3setNameTb4b4b4(Te6edf3meNameTb4b4b4)
Tb4b4b4.Te6edf3setKeyTb4b4b4(Te6edf3ourNodeTff7b72?.Te6edf3userTff7b72?.Te6edf3id Tff7b72?: Te6edf3NodeAddressTb4b4b4.Te6edf3ID_LOCALTb4b4b4)
Tb4b4b4.Te6edf3apply Tb4b4b4{
Te6edf3ourNodeTff7b72?.Te6edf3let Tb4b4b4{
Te6edf3setIconTb4b4b4(Te6edf3cachedPersonIconTb4b4b4(Tffa657itTb4b4b4.Te6edf3userTb4b4b4.Te6edf3idTb4b4b4, Tffa657itTb4b4b4.Te6edf3userTb4b4b4.Te6edf3short_nameTb4b4b4, Tffa657itTb4b4b4.Te6edf3colorsTb4b4b4.Te6edf3secondTb4b4b4, Tffa657itTb4b4b4.Te6edf3colorsTb4b4b4.Te6edf3firstTb4b4b4)Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3messagingStyle Tff7b72=
Te6edf3NotificationCompatTb4b4b4.Te6edf3MessagingStyleTb4b4b4(Te6edf3meTb4b4b4)
Tb4b4b4.Te6edf3setGroupConversationTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4.Te6edf3setConversationTitleTb4b4b4(Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3meshtastic_app_nameTb4b4b4)Tb4b4b4)
Te6edf3activeNotificationsTb4b4b4.Te6edf3forEach Tb4b4b4{ Te6edf3sbn Tff7b72-Tff7b72>
T8b949e// Prefer the child's real MessagingStyle: its latest message carries the actual sender (Person, icon) and
T8b949e// timestamp, so the summary line reads "Hawk Ridge: …" rather than the conversation title.
Tff7b72val Te6edf3latest Tff7b72=
Te6edf3NotificationCompatTb4b4b4.Te6edf3MessagingStyleTb4b4b4.Te6edf3extractMessagingStyleFromNotificationTb4b4b4(Te6edf3sbnTb4b4b4.Te6edf3notificationTb4b4b4)
Tff7b72?.Te6edf3messages
Tff7b72?.Te6edf3lastOrNullTb4b4b4(Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3latestTff7b72?.Te6edf3text Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3senderPerson Tff7b72= Te6edf3latestTb4b4b4.Te6edf3person Tff7b72?: Te6edf3PersonTb4b4b4.Te6edf3BuilderTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3setNameTb4b4b4(Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3youTb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Te6edf3messagingStyleTb4b4b4.Te6edf3addMessageTb4b4b4(Te6edf3latestTb4b4b4.Te6edf3textTb4b4b4, Te6edf3latestTb4b4b4.Te6edf3timestampTb4b4b4, Te6edf3senderPersonTb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
T8b949e// Fallback for children without an extractable style: rebuild a generic line from the extras.
Tff7b72val Te6edf3senderTitle Tff7b72= Te6edf3sbnTb4b4b4.Te6edf3notificationTb4b4b4.Te6edf3extrasTb4b4b4.Te6edf3getCharSequenceTb4b4b4(Te6edf3NotificationTb4b4b4.Te6edf3EXTRA_TITLETb4b4b4)
Tff7b72val Te6edf3messageText Tff7b72= Te6edf3sbnTb4b4b4.Te6edf3notificationTb4b4b4.Te6edf3extrasTb4b4b4.Te6edf3getCharSequenceTb4b4b4(Te6edf3NotificationTb4b4b4.Te6edf3EXTRA_TEXTTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3senderTitle Tff7b72!Tff7b72= Tff7b72null Tff7b72&Tff7b72& Te6edf3messageText Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3messagingStyleTb4b4b4.Te6edf3addMessageTb4b4b4(Te6edf3messageTextTb4b4b4, Te6edf3sbnTb4b4b4.Te6edf3postTimeTb4b4b4, Te6edf3PersonTb4b4b4.Te6edf3BuilderTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3setNameTb4b4b4(Te6edf3senderTitleTb4b4b4)Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72val Te6edf3summaryNotification Tff7b72=
Te6edf3commonBuilderTb4b4b4(Te6edf3NotificationTypeTb4b4b4.Te6edf3DirectMessageTb4b4b4)
Tb4b4b4.Te6edf3setSmallIconTb4b4b4(Te6edf3drawableTb4b4b4.Te6edf3meshtastic_ic_notificationTb4b4b4)
Tb4b4b4.Te6edf3setStyleTb4b4b4(Te6edf3messagingStyleTb4b4b4)
Tb4b4b4.Te6edf3setGroupTb4b4b4(Te6edf3GROUP_KEY_MESSAGESTb4b4b4)
Tb4b4b4.Te6edf3setGroupSummaryTb4b4b4(Tff7b72trueTb4b4b4)
T8b949e// Only the child conversation notifications alert; without this the summary (posted on a HIGH channel)
T8b949e// can buzz a second time for every message.
Tb4b4b4.Te6edf3setGroupAlertBehaviorTb4b4b4(Te6edf3NotificationCompatTb4b4b4.Te6edf3GROUP_ALERT_CHILDRENTb4b4b4)
Tb4b4b4.Te6edf3setAutoCancelTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Te6edf3notificationManagerTb4b4b4.Te6edf3notifyTb4b4b4(Te6edf3TAG_MESSAGE_SUMMARYTb4b4b4, Te6edf3SUMMARY_IDTb4b4b4, Te6edf3summaryNotificationTb4b4b4)
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffshowAlertNotificationTb4b4b4(Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4, Te6edf3nameTb4b4b4: Tffa657StringTb4b4b4, Te6edf3alertTb4b4b4: Tffa657StringTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3notification Tff7b72= Te6edf3createAlertNotificationTb4b4b4(Te6edf3contactKeyTb4b4b4, Te6edf3nameTb4b4b4, Te6edf3alertTb4b4b4)
T8b949e// Use a consistent, unique ID for each alert source.
Te6edf3notificationManagerTb4b4b4.Te6edf3notifyTb4b4b4(Te6edf3TAG_ALERTTb4b4b4, Te6edf3nameTb4b4b4.Te6edf3hashCodeTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3notificationTb4b4b4)
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffshowNewNodeSeenNotificationTb4b4b4(Te6edf3nodeTb4b4b4: Te6edf3NodeTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3notification Tff7b72= Te6edf3createNewNodeSeenNotificationTb4b4b4(Te6edf3nodeTb4b4b4.Te6edf3userTb4b4b4.Te6edf3short_nameTb4b4b4, Te6edf3nodeTb4b4b4.Te6edf3userTb4b4b4.Te6edf3long_nameTb4b4b4, Te6edf3nodeTb4b4b4.Te6edf3numTb4b4b4)
Te6edf3notificationManagerTb4b4b4.Te6edf3notifyTb4b4b4(Te6edf3TAG_NEW_NODETb4b4b4, Te6edf3nodeTb4b4b4.Te6edf3numTb4b4b4, Te6edf3notificationTb4b4b4)
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffshowOrUpdateLowBatteryNotificationTb4b4b4(Te6edf3nodeTb4b4b4: Te6edf3NodeTb4b4b4, Te6edf3isRemoteTb4b4b4: Tffa657BooleanTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3notification Tff7b72= Te6edf3createLowBatteryNotificationTb4b4b4(Te6edf3nodeTb4b4b4, Te6edf3isRemoteTb4b4b4)
Te6edf3notificationManagerTb4b4b4.Te6edf3notifyTb4b4b4(Te6edf3TAG_LOW_BATTERYTb4b4b4, Te6edf3nodeTb4b4b4.Te6edf3numTb4b4b4, Te6edf3notificationTb4b4b4)
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffshowClientNotificationTb4b4b4(Te6edf3clientNotificationTb4b4b4: Te6edf3ClientNotificationTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3notification Tff7b72=
Te6edf3createClientNotificationTb4b4b4(Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3client_notificationTb4b4b4)Tb4b4b4, Te6edf3clientNotificationTb4b4b4.Te6edf3messageTb4b4b4)
Te6edf3notificationManagerTb4b4b4.Te6edf3notifyTb4b4b4(Te6edf3TAG_CLIENTTb4b4b4, Te6edf3clientNotificationTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3hashCodeTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3notificationTb4b4b4)
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffcancelMessageNotificationTb4b4b4(Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3id Tff7b72= Te6edf3contactKeyTb4b4b4.Te6edf3hashCodeTb4b4b4(Tb4b4b4)
Te6edf3notificationManagerTb4b4b4.Te6edf3cancelTb4b4b4(Te6edf3TAG_MESSAGETb4b4b4, Te6edf3idTb4b4b4)
T8b949e// Rebuild (or clear) the group summary so it doesn't keep showing the dismissed conversation in Android Auto.
T8b949e// Pass the id we just cancelled so a stale activeNotifications snapshot doesn't keep the summary alive.
Te6edf3showGroupSummaryTb4b4b4(Te6edf3justCancelledId Tff7b72= Te6edf3idTb4b4b4)
Tb4b4b4}
T8b949e/**
* Re-posts the conversation silently after an inline reply, so the notification updates in place with the sent
* reply appended (the read context becomes historic, the reply is the visible latest message) instead of
* disappearing. Re-posting under the same (tag, id) is also what resolves the RemoteInput spinner.
*/
Tff7b72override Tff7b72suspend Tff7b72fun Td2a8ffrefreshConversationAfterReplyTb4b4b4(Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3isBroadcast Tff7b72= Te6edf3contactKeyTb4b4b4.Te6edf3containsTb4b4b4(Te6edf3NodeAddressTb4b4b4.Te6edf3ID_BROADCASTTb4b4b4)
Tff7b72val Te6edf3conversationNameTb4b4b4: Tffa657String
Tff7b72var Te6edf3channelNameTb4b4b4: Tffa657String? Tff7b72= Tff7b72null
Tff7b72if Tb4b4b4(Te6edf3isBroadcastTb4b4b4) Tb4b4b4{
T8b949e// Resolve the effective channel name (an empty primary shows its modem-preset name, e.g. "LongFast").
Tff7b72val Te6edf3channelSet Tff7b72= Te6edf3radioConfigRepositoryTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3channelSetFlowTb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3lora Tff7b72= Te6edf3channelSetTb4b4b4.Te6edf3lora_config Tff7b72?: Te6edf3ChannelTb4b4b4.Te6edf3defaultTb4b4b4.Te6edf3loraConfig
Tff7b72val Te6edf3index Tff7b72= Te6edf3contactKeyTb4b4b4.Te6edf3substringBeforeTb4b4b4(Te6edf3NodeAddressTb4b4b4.Te6edf3ID_BROADCASTTb4b4b4)Tb4b4b4.Te6edf3toIntOrNullTb4b4b4(Tb4b4b4)
Te6edf3channelName Tff7b72= Te6edf3indexTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3channelSetTb4b4b4.Te6edf3settingsTb4b4b4.Te6edf3getOrNullTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}Tff7b72?.Te6edf3let Tb4b4b4{ Te6edf3ChannelTb4b4b4(Tffa657itTb4b4b4, Te6edf3loraTb4b4b4)Tb4b4b4.Te6edf3name Tb4b4b4}
T8b949e// Never fall back to the raw contactKey for user-facing labels (privacy-first convention).
Te6edf3conversationName Tff7b72= Te6edf3channelName Tff7b72?: Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3channelTb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
T8b949e// DM contactKey is "<channelIndex><userId>" where userId starts at the '!'.
Tff7b72val Te6edf3userId Tff7b72= Ta5d6ff"Ta5d6ff!Ta5d6ff" Tff7b72+ Te6edf3contactKeyTb4b4b4.Te6edf3substringAfterTb4b4b4(Ta5d6ff"Ta5d6ff!Ta5d6ff"Tb4b4b4, Te6edf3missingDelimiterValue Tff7b72= Ta5d6ff"Ta5d6ff"Tb4b4b4)
Tff7b72val Te6edf3peer Tff7b72= Te6edf3nodeRepositoryTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3nodeDBbyNumTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3valuesTb4b4b4.Te6edf3find Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3userTb4b4b4.Te6edf3id Tff7b72=Tff7b72= Te6edf3userId Tb4b4b4}
Te6edf3conversationName Tff7b72=
Te6edf3peerTff7b72?.Te6edf3userTff7b72?.Te6edf3long_nameTff7b72?.Te6edf3takeIf Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3isNotBlankTb4b4b4(Tb4b4b4) Tb4b4b4} Tff7b72?: Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3unknown_usernameTb4b4b4)
Tb4b4b4}
Te6edf3showConversationNotificationTb4b4b4(Te6edf3contactKeyTb4b4b4, Te6edf3isBroadcastTb4b4b4, Te6edf3channelNameTb4b4b4, Te6edf3conversationNameTb4b4b4, Te6edf3isSilent Tff7b72= Tff7b72trueTb4b4b4)
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffcancelLowBatteryNotificationTb4b4b4(Te6edf3nodeTb4b4b4: Te6edf3NodeTb4b4b4) Tff7b72= Te6edf3notificationManagerTb4b4b4.Te6edf3cancelTb4b4b4(Te6edf3TAG_LOW_BATTERYTb4b4b4, Te6edf3nodeTb4b4b4.Te6edf3numTb4b4b4)
Tff7b72override Tff7b72fun Td2a8ffclearClientNotificationTb4b4b4(Te6edf3notificationTb4b4b4: Te6edf3ClientNotificationTb4b4b4) Tff7b72=
Te6edf3notificationManagerTb4b4b4.Te6edf3cancelTb4b4b4(Te6edf3TAG_CLIENTTb4b4b4, Te6edf3notificationTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3hashCodeTb4b4b4(Tb4b4b4)Tb4b4b4)
T8b949e// endregion
T8b949e// region Notification Creation
Tff7b72private Tff7b72fun Td2a8ffcreateServiceStateNotificationTb4b4b4(Te6edf3nameTb4b4b4: Tffa657StringTb4b4b4, Te6edf3messageTb4b4b4: Tffa657String?Tb4b4b4, Te6edf3nextUpdateAtTb4b4b4: Tffa657Long?Tb4b4b4)Tb4b4b4: Te6edf3Notification Tb4b4b4{
Tff7b72val Te6edf3builder Tff7b72=
Te6edf3commonBuilderTb4b4b4(Te6edf3NotificationTypeTb4b4b4.Te6edf3ServiceStateTb4b4b4)
Tb4b4b4.Te6edf3setPriorityTb4b4b4(Te6edf3NotificationCompatTb4b4b4.Te6edf3PRIORITY_MINTb4b4b4)
Tb4b4b4.Te6edf3setCategoryTb4b4b4(Te6edf3NotificationTb4b4b4.Te6edf3CATEGORY_SERVICETb4b4b4)
Tb4b4b4.Te6edf3setOngoingTb4b4b4(Tff7b72trueTb4b4b4)
T8b949e// Android 12+ may defer FGS notifications ~10s; show immediately so the user watching a
T8b949e// "Connecting…" state gets feedback right away.
Tb4b4b4.Te6edf3setForegroundServiceBehaviorTb4b4b4(Te6edf3NotificationCompatTb4b4b4.Te6edf3FOREGROUND_SERVICE_IMMEDIATETb4b4b4)
Tb4b4b4.Te6edf3setContentTitleTb4b4b4(Te6edf3nameTb4b4b4)
Tb4b4b4.Te6edf3setShowWhenTb4b4b4(Tff7b72trueTb4b4b4)
Te6edf3messageTff7b72?.Te6edf3let Tb4b4b4{
T8b949e// First line of message is used for collapsed view, ensure it doesn't have a bullet
Te6edf3builderTb4b4b4.Te6edf3setContentTextTb4b4b4(Tffa657itTb4b4b4.Te6edf3substringBeforeTb4b4b4(Ta5d6ff"Ta5d6ff\Ta5d6ffnTa5d6ff"Tb4b4b4)Tb4b4b4.Te6edf3removePrefixTb4b4b4(Te6edf3BULLETTb4b4b4)Tb4b4b4)
Te6edf3builderTb4b4b4.Te6edf3setStyleTb4b4b4(Te6edf3NotificationCompatTb4b4b4.Te6edf3BigTextStyleTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3bigTextTb4b4b4(Tffa657itTb4b4b4)Tb4b4b4)
Tb4b4b4}
Te6edf3nextUpdateAt
Tff7b72?.Te6edf3takeIf Tb4b4b4{ Tffa657it Tff7b72> Te6edf3nowMillis Tb4b4b4}
Tff7b72?.Te6edf3let Tb4b4b4{
Te6edf3builderTb4b4b4.Te6edf3setWhenTb4b4b4(Tffa657itTb4b4b4)
Te6edf3builderTb4b4b4.Te6edf3setUsesChronometerTb4b4b4(Tff7b72trueTb4b4b4)
Te6edf3builderTb4b4b4.Te6edf3setChronometerCountDownTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4}
Tff7b72return Te6edf3builderTb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffLongMethodTa5d6ff"Tb4b4b4)
Tff7b72private Tff7b72fun Td2a8ffcreateConversationNotificationTb4b4b4(
Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4,
Te6edf3isBroadcastTb4b4b4: Tffa657BooleanTb4b4b4,
Te6edf3channelNameTb4b4b4: Tffa657String?Tb4b4b4,
Te6edf3historyTb4b4b4: Te6edf3ListTff7b72<Te6edf3MessageTff7b72>Tb4b4b4,
Te6edf3isSilentTb4b4b4: Tffa657Boolean Tff7b72= Tff7b72falseTb4b4b4,
Tb4b4b4)Tb4b4b4: Te6edf3Notification Tb4b4b4{
Tff7b72val Te6edf3type Tff7b72= Tff7b72if Tb4b4b4(Te6edf3isBroadcastTb4b4b4) Te6edf3NotificationTypeTb4b4b4.Te6edf3BroadcastMessage Tff7b72else Te6edf3NotificationTypeTb4b4b4.Te6edf3DirectMessage
Tff7b72val Te6edf3builder Tff7b72= Te6edf3commonBuilderTb4b4b4(Te6edf3typeTb4b4b4, Te6edf3createOpenMessageIntentTb4b4b4(Te6edf3contactKeyTb4b4b4)Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3isSilentTb4b4b4) Tb4b4b4{
Te6edf3builderTb4b4b4.Te6edf3setSilentTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4}
Tff7b72val Te6edf3ourNode Tff7b72= Te6edf3nodeRepositoryTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3ourNodeInfoTb4b4b4.Te6edf3value
Tff7b72val Te6edf3meName Tff7b72= Te6edf3ourNodeTff7b72?.Te6edf3userTff7b72?.Te6edf3long_name Tff7b72?: Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3youTb4b4b4)
Tff7b72val Te6edf3me Tff7b72=
Te6edf3PersonTb4b4b4.Te6edf3BuilderTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3setNameTb4b4b4(Te6edf3meNameTb4b4b4)
Tb4b4b4.Te6edf3setKeyTb4b4b4(Te6edf3ourNodeTff7b72?.Te6edf3userTff7b72?.Te6edf3id Tff7b72?: Te6edf3NodeAddressTb4b4b4.Te6edf3ID_LOCALTb4b4b4)
Tb4b4b4.Te6edf3apply Tb4b4b4{
Te6edf3ourNodeTff7b72?.Te6edf3let Tb4b4b4{
Te6edf3setIconTb4b4b4(Te6edf3cachedPersonIconTb4b4b4(Tffa657itTb4b4b4.Te6edf3userTb4b4b4.Te6edf3idTb4b4b4, Tffa657itTb4b4b4.Te6edf3userTb4b4b4.Te6edf3short_nameTb4b4b4, Tffa657itTb4b4b4.Te6edf3colorsTb4b4b4.Te6edf3secondTb4b4b4, Tffa657itTb4b4b4.Te6edf3colorsTb4b4b4.Te6edf3firstTb4b4b4)Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3style Tff7b72=
Te6edf3NotificationCompatTb4b4b4.Te6edf3MessagingStyleTb4b4b4(Te6edf3meTb4b4b4)
Tb4b4b4.Te6edf3setGroupConversationTb4b4b4(Te6edf3channelName Tff7b72!Tff7b72= Tff7b72nullTb4b4b4)
Tb4b4b4.Te6edf3setConversationTitleTb4b4b4(Te6edf3channelNameTb4b4b4)
T8b949e// Already-read messages are added as *historic* context rather than as new content: MessagingStyle keeps them
T8b949e// available to accessibility services and Android Auto/Wear for conversation context without re-presenting them
T8b949e// as freshly-arrived messages. Unread messages (and reactions, which are themselves new events) are the actual
T8b949e// alerting content. When every message in the window is read (e.g. a reaction arrived on a read message) the
T8b949e// most recent one is kept as a normal message so the notification still has alerting content to show.
Tff7b72val Te6edf3anyUnread Tff7b72= Te6edf3historyTb4b4b4.Te6edf3any Tb4b4b4{ Tff7b72!Tffa657itTb4b4b4.Te6edf3read Tb4b4b4}
Tff7b72val Te6edf3lastIndex Tff7b72= Te6edf3historyTb4b4b4.Te6edf3lastIndex
Te6edf3historyTb4b4b4.Te6edf3forEachIndexed Tb4b4b4{ Te6edf3indexTb4b4b4, Te6edf3msg Tff7b72-Tff7b72>
T8b949e// Use the node attached to the message directly to ensure correct identification
Tff7b72val Te6edf3person Tff7b72=
Te6edf3PersonTb4b4b4.Te6edf3BuilderTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3setNameTb4b4b4(Te6edf3msgTb4b4b4.Te6edf3nodeTb4b4b4.Te6edf3userTb4b4b4.Te6edf3long_nameTb4b4b4)
Tb4b4b4.Te6edf3setKeyTb4b4b4(Te6edf3msgTb4b4b4.Te6edf3nodeTb4b4b4.Te6edf3userTb4b4b4.Te6edf3idTb4b4b4)
T8b949e// Favorite nodes feed the system's conversation-priority ranking (shade ordering, suggestions).
Tb4b4b4.Te6edf3setImportantTb4b4b4(Te6edf3msgTb4b4b4.Te6edf3nodeTb4b4b4.Te6edf3isFavoriteTb4b4b4)
Tb4b4b4.Te6edf3setIconTb4b4b4(
Te6edf3cachedPersonIconTb4b4b4(
Te6edf3msgTb4b4b4.Te6edf3nodeTb4b4b4.Te6edf3userTb4b4b4.Te6edf3idTb4b4b4,
Te6edf3msgTb4b4b4.Te6edf3nodeTb4b4b4.Te6edf3userTb4b4b4.Te6edf3short_nameTb4b4b4,
Te6edf3msgTb4b4b4.Te6edf3nodeTb4b4b4.Te6edf3colorsTb4b4b4.Te6edf3secondTb4b4b4,
Te6edf3msgTb4b4b4.Te6edf3nodeTb4b4b4.Te6edf3colorsTb4b4b4.Te6edf3firstTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3text Tff7b72=
Te6edf3msgTb4b4b4.Te6edf3originalMessageTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3original Tff7b72-Tff7b72>
Ta5d6ff"Ta5d6ff↩️ Ta5d6ff\"Tffd700${Te6edf3originalTb4b4b4.Te6edf3nodeTb4b4b4.Te6edf3userTb4b4b4.Te6edf3short_nameTffd700}Ta5d6ff: Tffd700${Te6edf3originalTb4b4b4.Te6edf3textTb4b4b4.Te6edf3takeTb4b4b4(Te6edf3SNIPPET_LENGTHTb4b4b4)Tffd700}Ta5d6ff...Ta5d6ff\"Ta5d6ff: Tffd700${Te6edf3msgTb4b4b4.Te6edf3textTffd700}Ta5d6ff"
Tb4b4b4} Tff7b72?: Te6edf3msgTb4b4b4.Te6edf3text
Tff7b72if Tb4b4b4(Te6edf3msgTb4b4b4.Te6edf3read Tff7b72&Tff7b72& Tb4b4b4(Te6edf3anyUnread Tff7b72|Tff7b72| Te6edf3index Tff7b72!Tff7b72= Te6edf3lastIndexTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3styleTb4b4b4.Te6edf3addHistoricMessageTb4b4b4(Te6edf3NotificationCompatTb4b4b4.Te6edf3MessagingStyleTb4b4b4.Te6edf3MessageTb4b4b4(Te6edf3textTb4b4b4, Te6edf3msgTb4b4b4.Te6edf3receivedTimeTb4b4b4, Te6edf3personTb4b4b4)Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3styleTb4b4b4.Te6edf3addMessageTb4b4b4(Te6edf3textTb4b4b4, Te6edf3msgTb4b4b4.Te6edf3receivedTimeTb4b4b4, Te6edf3personTb4b4b4)
Tb4b4b4}
T8b949e// Add reactions as separate "messages" in history if they exist
Te6edf3msgTb4b4b4.Te6edf3emojisTb4b4b4.Te6edf3forEach Tb4b4b4{ Te6edf3reaction Tff7b72-Tff7b72>
Tff7b72val Te6edf3reactorNode Tff7b72= Te6edf3nodeRepositoryTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3getNodeTb4b4b4(Te6edf3reactionTb4b4b4.Te6edf3userTb4b4b4.Te6edf3idTb4b4b4)
Tff7b72val Te6edf3reactor Tff7b72=
Te6edf3PersonTb4b4b4.Te6edf3BuilderTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3setNameTb4b4b4(Te6edf3reactionTb4b4b4.Te6edf3userTb4b4b4.Te6edf3long_nameTb4b4b4)
Tb4b4b4.Te6edf3setKeyTb4b4b4(Te6edf3reactionTb4b4b4.Te6edf3userTb4b4b4.Te6edf3idTb4b4b4)
Tb4b4b4.Te6edf3setIconTb4b4b4(
Te6edf3cachedPersonIconTb4b4b4(
Te6edf3reactionTb4b4b4.Te6edf3userTb4b4b4.Te6edf3idTb4b4b4,
Te6edf3reactionTb4b4b4.Te6edf3userTb4b4b4.Te6edf3short_nameTb4b4b4,
Te6edf3reactorNodeTb4b4b4.Te6edf3colorsTb4b4b4.Te6edf3secondTb4b4b4,
Te6edf3reactorNodeTb4b4b4.Te6edf3colorsTb4b4b4.Te6edf3firstTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Te6edf3styleTb4b4b4.Te6edf3addMessageTb4b4b4(
Ta5d6ff"Tffd700${Te6edf3reactionTb4b4b4.Te6edf3emojiTffd700}Ta5d6ff to Ta5d6ff\"Tffd700${Te6edf3msgTb4b4b4.Te6edf3textTb4b4b4.Te6edf3takeTb4b4b4(Te6edf3SNIPPET_LENGTHTb4b4b4)Tffd700}Ta5d6ff...Ta5d6ff\"Ta5d6ff"Tb4b4b4,
Te6edf3reactionTb4b4b4.Te6edf3timestampTb4b4b4,
Te6edf3reactorTb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72val Te6edf3lastMessage Tff7b72= Te6edf3historyTb4b4b4.Te6edf3lastTb4b4b4(Tb4b4b4)
Te6edf3builder
Tb4b4b4.Te6edf3setCategoryTb4b4b4(Te6edf3NotificationTb4b4b4.Te6edf3CATEGORY_MESSAGETb4b4b4)
T8b949e// Link to the conversation shortcut so this is treated as a Conversation notification (Android 11+).
Tb4b4b4.Te6edf3setShortcutIdTb4b4b4(Te6edf3contactKeyTb4b4b4)
Tb4b4b4.Te6edf3setLocusIdTb4b4b4(Te6edf3LocusIdCompatTb4b4b4(Te6edf3contactKeyTb4b4b4)Tb4b4b4)
Tb4b4b4.Te6edf3setAutoCancelTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4.Te6edf3setStyleTb4b4b4(Te6edf3styleTb4b4b4)
Tb4b4b4.Te6edf3setGroupTb4b4b4(Te6edf3GROUP_KEY_MESSAGESTb4b4b4)
Tb4b4b4.Te6edf3setVisibilityTb4b4b4(Te6edf3NotificationCompatTb4b4b4.Te6edf3VISIBILITY_PRIVATETb4b4b4)
Tb4b4b4.Te6edf3setWhenTb4b4b4(Te6edf3lastMessageTb4b4b4.Te6edf3receivedTimeTb4b4b4)
Tb4b4b4.Te6edf3setShowWhenTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4.Te6edf3addActionTb4b4b4(Te6edf3createReplyActionTb4b4b4(Te6edf3contactKeyTb4b4b4)Tb4b4b4)
Tb4b4b4.Te6edf3addActionTb4b4b4(Te6edf3createMarkAsReadActionTb4b4b4(Te6edf3contactKeyTb4b4b4)Tb4b4b4)
Tb4b4b4.Te6edf3addActionTb4b4b4(
Te6edf3createReactionActionTb4b4b4(
Te6edf3contactKey Tff7b72= Te6edf3contactKeyTb4b4b4,
Te6edf3packetId Tff7b72= Te6edf3lastMessageTb4b4b4.Te6edf3packetIdTb4b4b4,
Te6edf3toId Tff7b72= Te6edf3lastMessageTb4b4b4.Te6edf3nodeTb4b4b4.Te6edf3userTb4b4b4.Te6edf3idTb4b4b4,
Te6edf3channelIndex Tff7b72= Te6edf3lastMessageTb4b4b4.Te6edf3nodeTb4b4b4.Te6edf3channelTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72return Te6edf3builderTb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffcreateWaypointNotificationTb4b4b4(
Te6edf3nameTb4b4b4: Tffa657StringTb4b4b4,
Te6edf3messageTb4b4b4: Tffa657StringTb4b4b4,
Te6edf3waypointIdTb4b4b4: Tffa657IntTb4b4b4,
Te6edf3isSilentTb4b4b4: Tffa657BooleanTb4b4b4,
Tb4b4b4)Tb4b4b4: Te6edf3Notification Tb4b4b4{
Tff7b72val Te6edf3person Tff7b72= Te6edf3PersonTb4b4b4.Te6edf3BuilderTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3setNameTb4b4b4(Te6edf3nameTb4b4b4)Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3style Tff7b72= Te6edf3NotificationCompatTb4b4b4.Te6edf3MessagingStyleTb4b4b4(Te6edf3personTb4b4b4)Tb4b4b4.Te6edf3addMessageTb4b4b4(Te6edf3messageTb4b4b4, Te6edf3nowMillisTb4b4b4, Te6edf3personTb4b4b4)
Tff7b72val Te6edf3builder Tff7b72=
Te6edf3commonBuilderTb4b4b4(Te6edf3NotificationTypeTb4b4b4.Te6edf3WaypointTb4b4b4, Te6edf3createOpenWaypointIntentTb4b4b4(Te6edf3waypointIdTb4b4b4)Tb4b4b4)
Tb4b4b4.Te6edf3setCategoryTb4b4b4(Te6edf3NotificationTb4b4b4.Te6edf3CATEGORY_MESSAGETb4b4b4)
Tb4b4b4.Te6edf3setAutoCancelTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4.Te6edf3setStyleTb4b4b4(Te6edf3styleTb4b4b4)
Tb4b4b4.Te6edf3setGroupTb4b4b4(Te6edf3GROUP_KEY_MESSAGESTb4b4b4)
Tb4b4b4.Te6edf3setVisibilityTb4b4b4(Te6edf3NotificationCompatTb4b4b4.Te6edf3VISIBILITY_PRIVATETb4b4b4)
Tb4b4b4.Te6edf3setWhenTb4b4b4(Te6edf3nowMillisTb4b4b4)
Tb4b4b4.Te6edf3setShowWhenTb4b4b4(Tff7b72trueTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3isSilentTb4b4b4) Tb4b4b4{
Te6edf3builderTb4b4b4.Te6edf3setSilentTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4}
Tff7b72return Te6edf3builderTb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffcreateAlertNotificationTb4b4b4(Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4, Te6edf3nameTb4b4b4: Tffa657StringTb4b4b4, Te6edf3alertTb4b4b4: Tffa657StringTb4b4b4)Tb4b4b4: Te6edf3Notification Tb4b4b4{
Tff7b72val Te6edf3person Tff7b72= Te6edf3PersonTb4b4b4.Te6edf3BuilderTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3setNameTb4b4b4(Te6edf3nameTb4b4b4)Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3style Tff7b72= Te6edf3NotificationCompatTb4b4b4.Te6edf3MessagingStyleTb4b4b4(Te6edf3personTb4b4b4)Tb4b4b4.Te6edf3addMessageTb4b4b4(Te6edf3alertTb4b4b4, Te6edf3nowMillisTb4b4b4, Te6edf3personTb4b4b4)
Tff7b72return Te6edf3commonBuilderTb4b4b4(Te6edf3NotificationTypeTb4b4b4.Te6edf3AlertTb4b4b4, Te6edf3createOpenMessageIntentTb4b4b4(Te6edf3contactKeyTb4b4b4)Tb4b4b4)
Tb4b4b4.Te6edf3setPriorityTb4b4b4(Te6edf3NotificationCompatTb4b4b4.Te6edf3PRIORITY_HIGHTb4b4b4)
Tb4b4b4.Te6edf3setCategoryTb4b4b4(Te6edf3NotificationTb4b4b4.Te6edf3CATEGORY_ALARMTb4b4b4)
Tb4b4b4.Te6edf3setAutoCancelTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4.Te6edf3setStyleTb4b4b4(Te6edf3styleTb4b4b4)
Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffcreateNewNodeSeenNotificationTb4b4b4(Te6edf3nameTb4b4b4: Tffa657StringTb4b4b4, Te6edf3messageTb4b4b4: Tffa657StringTb4b4b4, Te6edf3nodeNumTb4b4b4: Tffa657IntTb4b4b4)Tb4b4b4: Te6edf3Notification Tb4b4b4{
Tff7b72val Te6edf3title Tff7b72= Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3new_node_seenTb4b4b4, Te6edf3nameTb4b4b4)
Tff7b72val Te6edf3builder Tff7b72=
Te6edf3commonBuilderTb4b4b4(Te6edf3NotificationTypeTb4b4b4.Te6edf3NewNodeTb4b4b4, Te6edf3createOpenNodeDetailIntentTb4b4b4(Te6edf3nodeNumTb4b4b4)Tb4b4b4)
Tb4b4b4.Te6edf3setCategoryTb4b4b4(Te6edf3NotificationTb4b4b4.Te6edf3CATEGORY_STATUSTb4b4b4)
Tb4b4b4.Te6edf3setAutoCancelTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4.Te6edf3setContentTitleTb4b4b4(Te6edf3titleTb4b4b4)
Tb4b4b4.Te6edf3setWhenTb4b4b4(Te6edf3nowMillisTb4b4b4)
Tb4b4b4.Te6edf3setShowWhenTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4.Te6edf3setContentTextTb4b4b4(Te6edf3messageTb4b4b4)
Tb4b4b4.Te6edf3setStyleTb4b4b4(Te6edf3NotificationCompatTb4b4b4.Te6edf3BigTextStyleTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3bigTextTb4b4b4(Te6edf3messageTb4b4b4)Tb4b4b4)
Tff7b72return Te6edf3builderTb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffcreateLowBatteryNotificationTb4b4b4(Te6edf3nodeTb4b4b4: Te6edf3NodeTb4b4b4, Te6edf3isRemoteTb4b4b4: Tffa657BooleanTb4b4b4)Tb4b4b4: Te6edf3Notification Tb4b4b4{
Tff7b72val Te6edf3type Tff7b72= Tff7b72if Tb4b4b4(Te6edf3isRemoteTb4b4b4) Te6edf3NotificationTypeTb4b4b4.Te6edf3LowBatteryRemote Tff7b72else Te6edf3NotificationTypeTb4b4b4.Te6edf3LowBatteryLocal
Tff7b72val Te6edf3title Tff7b72= Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3low_battery_titleTb4b4b4, Te6edf3nodeTb4b4b4.Te6edf3userTb4b4b4.Te6edf3short_nameTb4b4b4)
Tff7b72val Te6edf3batteryLevel Tff7b72= Te6edf3nodeTb4b4b4.Te6edf3deviceMetricsTb4b4b4.Te6edf3battery_level Tff7b72?: T79c0ff0
Tff7b72val Te6edf3message Tff7b72= Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3low_battery_messageTb4b4b4, Te6edf3nodeTb4b4b4.Te6edf3userTb4b4b4.Te6edf3long_nameTb4b4b4, Te6edf3batteryLevelTb4b4b4)
Tff7b72return Te6edf3commonBuilderTb4b4b4(Te6edf3typeTb4b4b4, Te6edf3createOpenNodeDetailIntentTb4b4b4(Te6edf3nodeTb4b4b4.Te6edf3numTb4b4b4)Tb4b4b4)
Tb4b4b4.Te6edf3setCategoryTb4b4b4(Te6edf3NotificationTb4b4b4.Te6edf3CATEGORY_STATUSTb4b4b4)
Tb4b4b4.Te6edf3setOngoingTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4.Te6edf3setOnlyAlertOnceTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4.Te6edf3setProgressTb4b4b4(Te6edf3MAX_BATTERY_LEVELTb4b4b4, Te6edf3batteryLevelTb4b4b4, Tff7b72falseTb4b4b4)
Tb4b4b4.Te6edf3setContentTitleTb4b4b4(Te6edf3titleTb4b4b4)
Tb4b4b4.Te6edf3setContentTextTb4b4b4(Te6edf3messageTb4b4b4)
Tb4b4b4.Te6edf3setStyleTb4b4b4(Te6edf3NotificationCompatTb4b4b4.Te6edf3BigTextStyleTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3bigTextTb4b4b4(Te6edf3messageTb4b4b4)Tb4b4b4)
Tb4b4b4.Te6edf3setWhenTb4b4b4(Te6edf3nowMillisTb4b4b4)
Tb4b4b4.Te6edf3setShowWhenTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffcreateClientNotificationTb4b4b4(Te6edf3nameTb4b4b4: Tffa657StringTb4b4b4, Te6edf3messageTb4b4b4: Tffa657StringTb4b4b4)Tb4b4b4: Te6edf3Notification Tff7b72=
Te6edf3commonBuilderTb4b4b4(Te6edf3NotificationTypeTb4b4b4.Te6edf3ClientTb4b4b4)
Tb4b4b4.Te6edf3setCategoryTb4b4b4(Te6edf3NotificationTb4b4b4.Te6edf3CATEGORY_ERRORTb4b4b4)
Tb4b4b4.Te6edf3setAutoCancelTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4.Te6edf3setContentTitleTb4b4b4(Te6edf3nameTb4b4b4)
Tb4b4b4.Te6edf3setContentTextTb4b4b4(Te6edf3messageTb4b4b4)
Tb4b4b4.Te6edf3setStyleTb4b4b4(Te6edf3NotificationCompatTb4b4b4.Te6edf3BigTextStyleTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3bigTextTb4b4b4(Te6edf3messageTb4b4b4)Tb4b4b4)
Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
T8b949e// endregion
T8b949e// region Helper/Builder Methods
Tff7b72private Tff7b72val Te6edf3openAppIntentTb4b4b4: Te6edf3PendingIntent Tff7b72by Te6edf3lazy Tb4b4b4{
Tff7b72val Te6edf3intent Tff7b72=
Te6edf3IntentTb4b4b4(Te6edf3contextTb4b4b4, Te6edf3ClassTb4b4b4.Te6edf3forNameTb4b4b4(Ta5d6ff"Ta5d6fforg.meshtastic.app.MainActivityTa5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{
Te6edf3flags Tff7b72= Te6edf3IntentTb4b4b4.Te6edf3FLAG_ACTIVITY_NEW_TASK Te6edf3or Te6edf3IntentTb4b4b4.Te6edf3FLAG_ACTIVITY_SINGLE_TOP
Tb4b4b4}
Te6edf3PendingIntentTb4b4b4.Te6edf3getActivityTb4b4b4(Te6edf3contextTb4b4b4, T79c0ff0Tb4b4b4, Te6edf3intentTb4b4b4, Te6edf3PendingIntentTb4b4b4.Te6edf3FLAG_IMMUTABLE Te6edf3or Te6edf3PendingIntentTb4b4b4.Te6edf3FLAG_UPDATE_CURRENTTb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffcreateOpenMessageIntentTb4b4b4(Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4)Tb4b4b4: Te6edf3PendingIntent Tb4b4b4{
Tff7b72val Te6edf3deepLinkUri Tff7b72= Ta5d6ff"Tffd700$Te6edf3DEEP_LINK_BASE_URITa5d6ff/messages/Tffd700$Te6edf3contactKeyTa5d6ff"Tb4b4b4.Te6edf3toUriTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3deepLinkIntent Tff7b72=
Te6edf3IntentTb4b4b4(Te6edf3IntentTb4b4b4.Te6edf3ACTION_VIEWTb4b4b4, Te6edf3deepLinkUriTb4b4b4, Te6edf3contextTb4b4b4, Te6edf3ClassTb4b4b4.Te6edf3forNameTb4b4b4(Ta5d6ff"Ta5d6fforg.meshtastic.app.MainActivityTa5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{
Te6edf3flags Tff7b72= Te6edf3IntentTb4b4b4.Te6edf3FLAG_ACTIVITY_SINGLE_TOP
Tb4b4b4}
Tff7b72return Te6edf3TaskStackBuilderTb4b4b4.Te6edf3createTb4b4b4(Te6edf3contextTb4b4b4)Tb4b4b4.Te6edf3run Tb4b4b4{
Te6edf3addNextIntentWithParentStackTb4b4b4(Te6edf3deepLinkIntentTb4b4b4)
Te6edf3getPendingIntentTb4b4b4(Te6edf3contactKeyTb4b4b4.Te6edf3hashCodeTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3PendingIntentTb4b4b4.Te6edf3FLAG_IMMUTABLE Te6edf3or Te6edf3PendingIntentTb4b4b4.Te6edf3FLAG_UPDATE_CURRENTTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffcreateOpenWaypointIntentTb4b4b4(Te6edf3waypointIdTb4b4b4: Tffa657IntTb4b4b4)Tb4b4b4: Te6edf3PendingIntent Tb4b4b4{
Tff7b72val Te6edf3deepLinkUri Tff7b72= Ta5d6ff"Tffd700$Te6edf3DEEP_LINK_BASE_URITa5d6ff/map?waypointId=Tffd700$Te6edf3waypointIdTa5d6ff"Tb4b4b4.Te6edf3toUriTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3deepLinkIntent Tff7b72=
Te6edf3IntentTb4b4b4(Te6edf3IntentTb4b4b4.Te6edf3ACTION_VIEWTb4b4b4, Te6edf3deepLinkUriTb4b4b4, Te6edf3contextTb4b4b4, Te6edf3ClassTb4b4b4.Te6edf3forNameTb4b4b4(Ta5d6ff"Ta5d6fforg.meshtastic.app.MainActivityTa5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{
Te6edf3flags Tff7b72= Te6edf3IntentTb4b4b4.Te6edf3FLAG_ACTIVITY_SINGLE_TOP
Tb4b4b4}
Tff7b72return Te6edf3TaskStackBuilderTb4b4b4.Te6edf3createTb4b4b4(Te6edf3contextTb4b4b4)Tb4b4b4.Te6edf3run Tb4b4b4{
Te6edf3addNextIntentWithParentStackTb4b4b4(Te6edf3deepLinkIntentTb4b4b4)
Te6edf3getPendingIntentTb4b4b4(Te6edf3waypointIdTb4b4b4, Te6edf3PendingIntentTb4b4b4.Te6edf3FLAG_IMMUTABLE Te6edf3or Te6edf3PendingIntentTb4b4b4.Te6edf3FLAG_UPDATE_CURRENTTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffcreateOpenNodeDetailIntentTb4b4b4(Te6edf3nodeNumTb4b4b4: Tffa657IntTb4b4b4)Tb4b4b4: Te6edf3PendingIntent Tb4b4b4{
Tff7b72val Te6edf3deepLinkUri Tff7b72= Ta5d6ff"Tffd700$Te6edf3DEEP_LINK_BASE_URITa5d6ff/nodes/Tffd700$Te6edf3nodeNumTa5d6ff"Tb4b4b4.Te6edf3toUriTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3deepLinkIntent Tff7b72=
Te6edf3IntentTb4b4b4(Te6edf3IntentTb4b4b4.Te6edf3ACTION_VIEWTb4b4b4, Te6edf3deepLinkUriTb4b4b4, Te6edf3contextTb4b4b4, Te6edf3ClassTb4b4b4.Te6edf3forNameTb4b4b4(Ta5d6ff"Ta5d6fforg.meshtastic.app.MainActivityTa5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{
Te6edf3flags Tff7b72= Te6edf3IntentTb4b4b4.Te6edf3FLAG_ACTIVITY_SINGLE_TOP
Tb4b4b4}
Tff7b72return Te6edf3TaskStackBuilderTb4b4b4.Te6edf3createTb4b4b4(Te6edf3contextTb4b4b4)Tb4b4b4.Te6edf3run Tb4b4b4{
Te6edf3addNextIntentWithParentStackTb4b4b4(Te6edf3deepLinkIntentTb4b4b4)
Te6edf3getPendingIntentTb4b4b4(Te6edf3nodeNumTb4b4b4, Te6edf3PendingIntentTb4b4b4.Te6edf3FLAG_IMMUTABLE Te6edf3or Te6edf3PendingIntentTb4b4b4.Te6edf3FLAG_UPDATE_CURRENTTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffcreateReplyActionTb4b4b4(Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4)Tb4b4b4: Te6edf3NotificationCompatTb4b4b4.Te6edf3Action Tb4b4b4{
Tff7b72val Te6edf3replyLabel Tff7b72= Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3replyTb4b4b4)
Tff7b72val Te6edf3remoteInput Tff7b72= Te6edf3RemoteInputTb4b4b4.Te6edf3BuilderTb4b4b4(Te6edf3KEY_TEXT_REPLYTb4b4b4)Tb4b4b4.Te6edf3setLabelTb4b4b4(Te6edf3replyLabelTb4b4b4)Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3replyIntent Tff7b72=
Te6edf3IntentTb4b4b4(Te6edf3contextTb4b4b4, Te6edf3ReplyReceiverTff7b72::Te6edf3classTb4b4b4.Te6edf3javaTb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{
Te6edf3action Tff7b72= Te6edf3ReplyReceiverTb4b4b4.Te6edf3REPLY_ACTION
Te6edf3putExtraTb4b4b4(Te6edf3ReplyReceiverTb4b4b4.Te6edf3CONTACT_KEYTb4b4b4, Te6edf3contactKeyTb4b4b4)
Tb4b4b4}
Tff7b72val Te6edf3replyPendingIntent Tff7b72=
Te6edf3PendingIntentTb4b4b4.Te6edf3getBroadcastTb4b4b4(
Te6edf3contextTb4b4b4,
Te6edf3contactKeyTb4b4b4.Te6edf3hashCodeTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3replyIntentTb4b4b4,
Te6edf3PendingIntentTb4b4b4.Te6edf3FLAG_MUTABLE Te6edf3or Te6edf3PendingIntentTb4b4b4.Te6edf3FLAG_UPDATE_CURRENTTb4b4b4,
Tb4b4b4)
Tff7b72return Te6edf3NotificationCompatTb4b4b4.Te6edf3ActionTb4b4b4.Te6edf3BuilderTb4b4b4(Te6edf3androidTb4b4b4.Te6edf3RTb4b4b4.Te6edf3drawableTb4b4b4.Te6edf3ic_menu_sendTb4b4b4, Te6edf3replyLabelTb4b4b4, Te6edf3replyPendingIntentTb4b4b4)
Tb4b4b4.Te6edf3addRemoteInputTb4b4b4(Te6edf3remoteInputTb4b4b4)
T8b949e// Required for Android Auto to drive reply hands-free without opening any UI.
Tb4b4b4.Te6edf3setSemanticActionTb4b4b4(Te6edf3NotificationCompatTb4b4b4.Te6edf3ActionTb4b4b4.Te6edf3SEMANTIC_ACTION_REPLYTb4b4b4)
Tb4b4b4.Te6edf3setShowsUserInterfaceTb4b4b4(Tff7b72falseTb4b4b4)
Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffcreateMarkAsReadActionTb4b4b4(Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4)Tb4b4b4: Te6edf3NotificationCompatTb4b4b4.Te6edf3Action Tb4b4b4{
Tff7b72val Te6edf3label Tff7b72= Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3mark_as_readTb4b4b4)
Tff7b72val Te6edf3intent Tff7b72=
Te6edf3IntentTb4b4b4(Te6edf3contextTb4b4b4, Te6edf3MarkAsReadReceiverTff7b72::Te6edf3classTb4b4b4.Te6edf3javaTb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{
Te6edf3action Tff7b72= Te6edf3MARK_AS_READ_ACTION
Te6edf3putExtraTb4b4b4(Te6edf3MarkAsReadReceiverTb4b4b4.Te6edf3CONTACT_KEYTb4b4b4, Te6edf3contactKeyTb4b4b4)
Tb4b4b4}
Tff7b72val Te6edf3pendingIntent Tff7b72=
Te6edf3PendingIntentTb4b4b4.Te6edf3getBroadcastTb4b4b4(
Te6edf3contextTb4b4b4,
Te6edf3contactKeyTb4b4b4.Te6edf3hashCodeTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3intentTb4b4b4,
Te6edf3PendingIntentTb4b4b4.Te6edf3FLAG_UPDATE_CURRENT Te6edf3or Te6edf3PendingIntentTb4b4b4.Te6edf3FLAG_IMMUTABLETb4b4b4,
Tb4b4b4)
Tff7b72return Te6edf3NotificationCompatTb4b4b4.Te6edf3ActionTb4b4b4.Te6edf3BuilderTb4b4b4(Te6edf3androidTb4b4b4.Te6edf3RTb4b4b4.Te6edf3drawableTb4b4b4.Te6edf3ic_menu_viewTb4b4b4, Te6edf3labelTb4b4b4, Te6edf3pendingIntentTb4b4b4)
T8b949e// Required for Android Auto to mark a conversation read hands-free without opening any UI.
Tb4b4b4.Te6edf3setSemanticActionTb4b4b4(Te6edf3NotificationCompatTb4b4b4.Te6edf3ActionTb4b4b4.Te6edf3SEMANTIC_ACTION_MARK_AS_READTb4b4b4)
Tb4b4b4.Te6edf3setShowsUserInterfaceTb4b4b4(Tff7b72falseTb4b4b4)
Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffcreateReactionActionTb4b4b4(
Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4,
Te6edf3packetIdTb4b4b4: Tffa657IntTb4b4b4,
Te6edf3toIdTb4b4b4: Tffa657StringTb4b4b4,
Te6edf3channelIndexTb4b4b4: Tffa657IntTb4b4b4,
Tb4b4b4)Tb4b4b4: Te6edf3NotificationCompatTb4b4b4.Te6edf3Action Tb4b4b4{
Tff7b72val Te6edf3label Tff7b72= Ta5d6ff"Ta5d6ff👍Ta5d6ff"
Tff7b72val Te6edf3intent Tff7b72=
Te6edf3IntentTb4b4b4(Te6edf3contextTb4b4b4, Te6edf3ReactionReceiverTff7b72::Te6edf3classTb4b4b4.Te6edf3javaTb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{
Te6edf3action Tff7b72= Te6edf3REACT_ACTION
Te6edf3putExtraTb4b4b4(Te6edf3ReactionReceiverTb4b4b4.Te6edf3EXTRA_CONTACT_KEYTb4b4b4, Te6edf3contactKeyTb4b4b4)
Te6edf3putExtraTb4b4b4(Te6edf3ReactionReceiverTb4b4b4.Te6edf3EXTRA_REPLY_IDTb4b4b4, Te6edf3packetIdTb4b4b4)
Te6edf3putExtraTb4b4b4(Te6edf3ReactionReceiverTb4b4b4.Te6edf3EXTRA_TO_IDTb4b4b4, Te6edf3toIdTb4b4b4)
Te6edf3putExtraTb4b4b4(Te6edf3ReactionReceiverTb4b4b4.Te6edf3EXTRA_CHANNEL_INDEXTb4b4b4, Te6edf3channelIndexTb4b4b4)
Te6edf3putExtraTb4b4b4(Te6edf3ReactionReceiverTb4b4b4.Te6edf3EXTRA_EMOJITb4b4b4, Ta5d6ff"Ta5d6ff👍Ta5d6ff"Tb4b4b4)
Tb4b4b4}
Tff7b72val Te6edf3pendingIntent Tff7b72=
Te6edf3PendingIntentTb4b4b4.Te6edf3getBroadcastTb4b4b4(
Te6edf3contextTb4b4b4,
Te6edf3packetIdTb4b4b4,
Te6edf3intentTb4b4b4,
Te6edf3PendingIntentTb4b4b4.Te6edf3FLAG_UPDATE_CURRENT Te6edf3or Te6edf3PendingIntentTb4b4b4.Te6edf3FLAG_IMMUTABLETb4b4b4,
Tb4b4b4)
Tff7b72return Te6edf3NotificationCompatTb4b4b4.Te6edf3ActionTb4b4b4.Te6edf3BuilderTb4b4b4(Te6edf3androidTb4b4b4.Te6edf3RTb4b4b4.Te6edf3drawableTb4b4b4.Te6edf3ic_menu_addTb4b4b4, Te6edf3labelTb4b4b4, Te6edf3pendingIntentTb4b4b4)Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffcommonBuilderTb4b4b4(
Te6edf3typeTb4b4b4: Te6edf3NotificationTypeTb4b4b4,
Te6edf3contentIntentTb4b4b4: Te6edf3PendingIntent? Tff7b72= Tff7b72nullTb4b4b4,
Tb4b4b4)Tb4b4b4: Te6edf3NotificationCompatTb4b4b4.Te6edf3Builder Tb4b4b4{
Tff7b72val Te6edf3smallIcon Tff7b72= Te6edf3drawableTb4b4b4.Te6edf3meshtastic_ic_notification
Tff7b72return Te6edf3NotificationCompatTb4b4b4.Te6edf3BuilderTb4b4b4(Te6edf3contextTb4b4b4, Te6edf3typeTb4b4b4.Te6edf3channelIdTb4b4b4)
Tb4b4b4.Te6edf3setSmallIconTb4b4b4(Te6edf3smallIconTb4b4b4)
Tb4b4b4.Te6edf3setColorTb4b4b4(Te6edf3NOTIFICATION_COLORTb4b4b4)
Tb4b4b4.Te6edf3setVisibilityTb4b4b4(Te6edf3NotificationCompatTb4b4b4.Te6edf3VISIBILITY_PUBLICTb4b4b4)
Tb4b4b4.Te6edf3setContentIntentTb4b4b4(Te6edf3contentIntent Tff7b72?: Te6edf3openAppIntentTb4b4b4)
Tb4b4b4}
T8b949e// endregion
T8b949e// region Extension Functions (Localized)
Tff7b72private Tff7b72fun Te6edf3LocalStatsTb4b4b4.Td2a8ffformatToStringTb4b4b4(Te6edf3batteryLevelTb4b4b4: Tffa657Int? Tff7b72= Tff7b72nullTb4b4b4)Tb4b4b4: Tffa657String Tb4b4b4{
Tff7b72val Te6edf3parts Tff7b72= Te6edf3mutableListOfTff7b72<Tffa657StringTff7b72>Tb4b4b4(Tb4b4b4)
Te6edf3batteryLevelTff7b72?.Te6edf3let Tb4b4b4{
Tff7b72if Tb4b4b4(Tffa657it Tff7b72> Te6edf3MAX_BATTERY_LEVELTb4b4b4) Tb4b4b4{
Te6edf3partsTb4b4b4.Te6edf3addTb4b4b4(Te6edf3BULLET Tff7b72+ Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3poweredTb4b4b4)Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3partsTb4b4b4.Te6edf3addTb4b4b4(Te6edf3BULLET Tff7b72+ Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3local_stats_batteryTb4b4b4, Tffa657itTb4b4b4)Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Te6edf3partsTb4b4b4.Te6edf3addTb4b4b4(Te6edf3BULLET Tff7b72+ Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3local_stats_nodesTb4b4b4, Te6edf3num_online_nodesTb4b4b4, Te6edf3num_total_nodesTb4b4b4)Tb4b4b4)
Te6edf3partsTb4b4b4.Te6edf3addTb4b4b4(Te6edf3BULLET Tff7b72+ Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3local_stats_uptimeTb4b4b4, Te6edf3formatUptimeTb4b4b4(Te6edf3uptime_secondsTb4b4b4)Tb4b4b4)Tb4b4b4)
Te6edf3partsTb4b4b4.Te6edf3addTb4b4b4(
Te6edf3BULLET Tff7b72+
Te6edf3getStringTb4b4b4(
Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3local_stats_utilizationTb4b4b4,
Te6edf3NumberFormatterTb4b4b4.Te6edf3formatTb4b4b4(Te6edf3channel_utilizationTb4b4b4.Te6edf3toDoubleTb4b4b4(Tb4b4b4)Tb4b4b4, T79c0ff2Tb4b4b4)Tb4b4b4,
Te6edf3NumberFormatterTb4b4b4.Te6edf3formatTb4b4b4(Te6edf3air_util_txTb4b4b4.Te6edf3toDoubleTb4b4b4(Tb4b4b4)Tb4b4b4, T79c0ff2Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3heap_free_bytes Tff7b72> T79c0ff0 Tff7b72|Tff7b72| Te6edf3heap_total_bytes Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3partsTb4b4b4.Te6edf3addTb4b4b4(
Te6edf3BULLET Tff7b72+
Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3local_stats_heapTb4b4b4) Tff7b72+
Ta5d6ff"Ta5d6ff: Ta5d6ff" Tff7b72+
Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3local_stats_heap_valueTb4b4b4, Te6edf3heap_free_bytesTb4b4b4, Te6edf3heap_total_bytesTb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
T8b949e// Traffic Stats
Tff7b72if Tb4b4b4(Te6edf3num_packets_tx Tff7b72> T79c0ff0 Tff7b72|Tff7b72| Te6edf3num_packets_rx Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3partsTb4b4b4.Te6edf3addTb4b4b4(Te6edf3BULLET Tff7b72+ Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3local_stats_trafficTb4b4b4, Te6edf3num_packets_txTb4b4b4, Te6edf3num_packets_rxTb4b4b4, Te6edf3num_rx_dupeTb4b4b4)Tb4b4b4)
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3num_tx_relay Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3partsTb4b4b4.Te6edf3addTb4b4b4(Te6edf3BULLET Tff7b72+ Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3local_stats_relaysTb4b4b4, Te6edf3num_tx_relayTb4b4b4, Te6edf3num_tx_relay_canceledTb4b4b4)Tb4b4b4)
Tb4b4b4}
T8b949e// Diagnostic Fields
Tff7b72val Te6edf3diagnosticParts Tff7b72= Te6edf3mutableListOfTff7b72<Tffa657StringTff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3noise_floor Tff7b72!Tff7b72= T79c0ff0Tb4b4b4) Te6edf3diagnosticPartsTb4b4b4.Te6edf3addTb4b4b4(Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3local_stats_noiseTb4b4b4, Te6edf3noise_floorTb4b4b4)Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3num_packets_rx_bad Tff7b72> T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3diagnosticPartsTb4b4b4.Te6edf3addTb4b4b4(Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3local_stats_badTb4b4b4, Te6edf3num_packets_rx_badTb4b4b4)Tb4b4b4)
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3num_tx_dropped Tff7b72> T79c0ff0Tb4b4b4) Te6edf3diagnosticPartsTb4b4b4.Te6edf3addTb4b4b4(Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3local_stats_droppedTb4b4b4, Te6edf3num_tx_droppedTb4b4b4)Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3diagnosticPartsTb4b4b4.Te6edf3isNotEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3partsTb4b4b4.Te6edf3addTb4b4b4(
Te6edf3BULLET Tff7b72+ Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3local_stats_diagnostics_prefixTb4b4b4, Te6edf3diagnosticPartsTb4b4b4.Te6edf3joinToStringTb4b4b4(Ta5d6ff"Ta5d6ff | Ta5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tff7b72return Te6edf3partsTb4b4b4.Te6edf3joinToStringTb4b4b4(Ta5d6ff"Ta5d6ff\Ta5d6ffnTa5d6ff"Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Te6edf3DeviceMetricsTb4b4b4.Td2a8ffformatToStringTb4b4b4(Tb4b4b4)Tb4b4b4: Tffa657String Tb4b4b4{
Tff7b72val Te6edf3parts Tff7b72= Te6edf3mutableListOfTff7b72<Tffa657StringTff7b72>Tb4b4b4(Tb4b4b4)
Te6edf3battery_levelTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3partsTb4b4b4.Te6edf3addTb4b4b4(Te6edf3BULLET Tff7b72+ Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3local_stats_batteryTb4b4b4, Tffa657itTb4b4b4)Tb4b4b4) Tb4b4b4}
Te6edf3uptime_secondsTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3partsTb4b4b4.Te6edf3addTb4b4b4(Te6edf3BULLET Tff7b72+ Te6edf3getStringTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3local_stats_uptimeTb4b4b4, Te6edf3formatUptimeTb4b4b4(Tffa657itTb4b4b4)Tb4b4b4)Tb4b4b4) Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3channel_utilization Tff7b72!Tff7b72= Tff7b72null Tff7b72|Tff7b72| Te6edf3air_util_tx Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3partsTb4b4b4.Te6edf3addTb4b4b4(
Te6edf3BULLET Tff7b72+
Te6edf3getStringTb4b4b4(
Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3local_stats_utilizationTb4b4b4,
Te6edf3NumberFormatterTb4b4b4.Te6edf3formatTb4b4b4(Tb4b4b4(Te6edf3channel_utilization Tff7b72?: T79c0ff0fTb4b4b4)Tb4b4b4.Te6edf3toDoubleTb4b4b4(Tb4b4b4)Tb4b4b4, T79c0ff2Tb4b4b4)Tb4b4b4,
Te6edf3NumberFormatterTb4b4b4.Te6edf3formatTb4b4b4(Tb4b4b4(Te6edf3air_util_tx Tff7b72?: T79c0ff0fTb4b4b4)Tb4b4b4.Te6edf3toDoubleTb4b4b4(Tb4b4b4)Tb4b4b4, T79c0ff2Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tff7b72return Te6edf3partsTb4b4b4.Te6edf3joinToStringTb4b4b4(Ta5d6ff"Ta5d6ff\Ta5d6ffnTa5d6ff"Tb4b4b4)
Tb4b4b4}
T8b949e// endregion
Tb4b4b4}
Served by rngit 1.5.2 - Generated in 0.38s